schedules and events from jarmod

This commit is contained in:
gnembon committed 2019-06-02 01:54:22 -03:00
1 parent 4ec6e0e03e
commit 730446b219
14 files changed
+825 -62

No files matched your search

+1
View File
@@ -46,6 +46,7 @@ public class CarpetServer // static for now - easier to handle all around the co
{ {
TickSpeed.tick(server); TickSpeed.tick(server);
HUDController.update_hud(server); HUDController.update_hud(server);
scriptServer.events.tick();
//in case something happens //in case something happens
CarpetSettings.impendingFillSkipUpdates = false; CarpetSettings.impendingFillSkipUpdates = false;
} }
@@ -2,6 +2,7 @@ package carpet.commands;
import carpet.CarpetServer; import carpet.CarpetServer;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import carpet.script.CarpetEventServer;
import carpet.script.CarpetExpression; import carpet.script.CarpetExpression;
import carpet.script.Expression; import carpet.script.Expression;
import carpet.script.ExpressionInspector; import carpet.script.ExpressionInspector;
@@ -193,9 +194,42 @@ public class ScriptCommand
return success?1:0; return success?1:0;
})); }));
LiteralArgumentBuilder<ServerCommandSource> q = literal("event").requires( (player) -> player.hasPermissionLevel(2) ).
executes( (cc) -> listEvents(cc.getSource())).
then(literal("add_to").
then(argument("event", StringArgumentType.word()).
suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.events.eventHandlers.keySet() ,bb)).
then(argument("call", StringArgumentType.word()).
suggests( (cc, bb) -> suggestMatching(suggestFunctionCalls(cc), bb)).
executes( (cc) -> CarpetServer.scriptServer.events.addEvent(
StringArgumentType.getString(cc, "event"),
null,
StringArgumentType.getString(cc, "call")
)?1:0)).
then(literal("from").
then(argument("package", StringArgumentType.word()).
suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.modules.keySet(), bb)).
then(argument("call", StringArgumentType.word()).
suggests( (cc, bb) -> suggestMatching(suggestFunctionCalls(cc), bb)).
executes( (cc) -> CarpetServer.scriptServer.events.addEvent(
StringArgumentType.getString(cc, "event"),
StringArgumentType.getString(cc, "package"),
StringArgumentType.getString(cc, "call")
)?1:0)))))).
then(literal("remove_from").
then(argument("event", StringArgumentType.word()).
suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.events.eventHandlers.keySet() ,bb)).
then(argument("call", StringArgumentType.greedyString()).
suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.events.eventHandlers.get(StringArgumentType.getString(cc, "event")).callList.stream().map(CarpetEventServer.Callback::toString), bb)).
executes( (cc) -> CarpetServer.scriptServer.events.removeEvent(
StringArgumentType.getString(cc, "event"),
StringArgumentType.getString(cc, "call")
)?1:0))));
dispatcher.register(literal("script"). dispatcher.register(literal("script").
requires((player) -> CarpetSettings.getBool("commandScript")). requires((player) -> CarpetSettings.getBool("commandScript")).
then(b).then(u).then(o).then(l).then(s).then(c).then(h).then(i).then(e).then(t).then(a).then(f)); then(b).then(u).then(o).then(l).then(s).then(c).then(h).then(i).then(e).then(t).then(a).then(f).then(q));
dispatcher.register(literal("script"). dispatcher.register(literal("script").
requires((player) -> CarpetSettings.getBool("commandScript")). requires((player) -> CarpetSettings.getBool("commandScript")).
then(literal("in"). then(literal("in").
@@ -222,6 +256,24 @@ public class ScriptCommand
ScriptHost host = getHost(c); ScriptHost host = getHost(c);
return host.getPublicFunctions(); return host.getPublicFunctions();
} }
private static int listEvents(ServerCommandSource source)
{
Messenger.m(source, "w Lists ALL event handlers:");
for (String event: CarpetServer.scriptServer.events.eventHandlers.keySet())
{
boolean shownEvent = false;
for (CarpetEventServer.Callback c: CarpetServer.scriptServer.events.eventHandlers.get(event).callList)
{
if (!shownEvent)
{
Messenger.m(source, "w Handlers for "+event+": ");
shownEvent = true;
}
Messenger.m(source, "w - "+c.udf+(c.host==null?"":" (from "+c.host+")"));
}
}
return 1;
}
private static int listGlobals(CommandContext<ServerCommandSource> context) private static int listGlobals(CommandContext<ServerCommandSource> context)
{ {
ScriptHost host = getHost(context); ScriptHost host = getHost(context);
@@ -1,5 +1,6 @@
package carpet.mixins; package carpet.mixins;
import carpet.CarpetServer;
import carpet.fakes.MinecraftServerInterface; import carpet.fakes.MinecraftServerInterface;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ServerTask; import net.minecraft.server.ServerTask;
@@ -7,6 +8,9 @@ import net.minecraft.util.NonBlockingThreadExecutor;
import net.minecraft.util.SystemUtil; import net.minecraft.util.SystemUtil;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.function.BooleanSupplier; import java.util.function.BooleanSupplier;
@@ -31,4 +35,13 @@ public abstract class MinecraftServer_scarpetMixin extends NonBlockingThreadExec
tick(isAhead); tick(isAhead);
executeTaskQueue(); executeTaskQueue();
} }
@Inject(method = "tick", at = @At(
value = "CONSTANT",
args = "stringValue=tallying"
))
public void tickTasks(BooleanSupplier booleanSupplier_1, CallbackInfo ci)
{
CarpetServer.scriptServer.events.onTick();
}
} }
@@ -0,0 +1,153 @@
package carpet.mixins;
import carpet.CarpetServer;
import carpet.CarpetSettings;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.network.packet.ClientCommandC2SPacket;
import net.minecraft.server.network.packet.PlayerActionC2SPacket;
import net.minecraft.server.network.packet.PlayerInputC2SPacket;
import net.minecraft.server.network.packet.PlayerInteractBlockC2SPacket;
import net.minecraft.server.network.packet.PlayerInteractEntityC2SPacket;
import net.minecraft.server.network.packet.PlayerInteractItemC2SPacket;
import net.minecraft.server.network.packet.PlayerMoveC2SPacket;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ServerPlayNetworkHandler.class)
public class ServerPlayNetworkHandler_scarpetEventsMixin
{
@Shadow public ServerPlayerEntity player;
@Inject(method = "onPlayerInput", at = @At(value = "RETURN"))
private void checkMoves(PlayerInputC2SPacket p, CallbackInfo ci)
{
if (p.getSideways() != 0.0F || p.getForward() != 0.0F || p.isJumping() || p.isSneaking())
{
CarpetServer.scriptServer.events.onMountControls(player, p.getSideways(), p.getForward(), p.isJumping(), p.isSneaking());
}
}
@Inject(method = "onPlayerMove", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;jump()V"
))
private void onJump(PlayerMoveC2SPacket playerMoveC2SPacket_1, CallbackInfo ci)
{
CarpetServer.scriptServer.events.onPlayerJumped(player);
}
@Inject(method = "onPlayerAction", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerInteractionManager;method_14263(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;)V"
))
private void onClicked(PlayerActionC2SPacket packet, CallbackInfo ci)
{
CarpetServer.scriptServer.events.onBlockClicked(player, packet.getPos(), packet.getDirection());
}
@Inject(method = "onPlayerInteractBlock", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerInteractionManager;interactBlock(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/world/World;Lnet/minecraft/item/ItemStack;Lnet/minecraft/util/Hand;Lnet/minecraft/util/hit/BlockHitResult;)Lnet/minecraft/util/ActionResult;"
))
private void onBlockInteracted(PlayerInteractBlockC2SPacket playerInteractBlockC2SPacket_1, CallbackInfo ci)
{
Hand hand = playerInteractBlockC2SPacket_1.getHand();
BlockHitResult hitRes = playerInteractBlockC2SPacket_1.getHitY();
CarpetServer.scriptServer.events.onRightClickBlock(player, hand, hitRes );
}
@Inject(method = "onPlayerInteractItem", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;updateLastActionTime()V"
))
private void onItemClicked(PlayerInteractItemC2SPacket playerInteractItemC2SPacket_1, CallbackInfo ci)
{
CarpetServer.scriptServer.events.onRightClick(player, playerInteractItemC2SPacket_1.getHand());
}
@Inject(method = "onClientCommand", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;setSneaking(Z)V",
ordinal = 0
))
private void onStartSneaking(ClientCommandC2SPacket clientCommandC2SPacket_1, CallbackInfo ci)
{
CarpetServer.scriptServer.events.onStartSneaking(player);
}
@Inject(method = "onClientCommand", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;setSneaking(Z)V",
ordinal = 1
))
private void onStopSneaking(ClientCommandC2SPacket clientCommandC2SPacket_1, CallbackInfo ci)
{
CarpetServer.scriptServer.events.onStopSneaking(player);
}
@Inject(method = "onClientCommand", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;setSprinting(Z)V",
ordinal = 0
))
private void onStartSprinting(ClientCommandC2SPacket clientCommandC2SPacket_1, CallbackInfo ci)
{
CarpetServer.scriptServer.events.onStartSprinting(player);
}
@Inject(method = "onClientCommand", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;setSprinting(Z)V",
ordinal = 1
))
private void onStopSprinting(ClientCommandC2SPacket clientCommandC2SPacket_1, CallbackInfo ci)
{
CarpetServer.scriptServer.events.onStopSprinting(player);
}
@Inject(method = "onClientCommand", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;isSleeping()Z",
shift = At.Shift.BEFORE
))
private void onWakeUp(ClientCommandC2SPacket clientCommandC2SPacket_1, CallbackInfo ci)
{
//weird one - doesn't seem to work, maybe MP
CarpetServer.scriptServer.events.onOutOfBed(player);
}
@Inject(method = "onClientCommand", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;isFallFlying()Z",
shift = At.Shift.BEFORE
))
private void onElytraEngage(ClientCommandC2SPacket clientCommandC2SPacket_1, CallbackInfo ci)
{
CarpetServer.scriptServer.events.onElytraDeploy(player);
}
@Inject(method = "onPlayerInteractEntity", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;interact(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/Hand;)Lnet/minecraft/util/ActionResult;"
))
private void onEntityInteract(PlayerInteractEntityC2SPacket playerInteractEntityC2SPacket_1, CallbackInfo ci)
{
CarpetServer.scriptServer.events.onEntityInteracted(player, playerInteractEntityC2SPacket_1.getEntity(player.getServerWorld()), playerInteractEntityC2SPacket_1.getHand());
}
@Inject(method = "onPlayerInteractEntity", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;attack(Lnet/minecraft/entity/Entity;)V"
))
private void onEntityAttack(PlayerInteractEntityC2SPacket playerInteractEntityC2SPacket_1, CallbackInfo ci)
{
//todo add hit and hand in the future
CarpetServer.scriptServer.events.onEntityAttacked(player, playerInteractEntityC2SPacket_1.getEntity(player.getServerWorld()));
}
}
@@ -0,0 +1,29 @@
package carpet.mixins;
import carpet.CarpetServer;
import net.minecraft.block.BlockState;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.network.ServerPlayerInteractionManager;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(ServerPlayerInteractionManager.class)
public class ServerPlayerInteractionManager_scarpetEventsMixin
{
@Shadow public ServerPlayerEntity player;
@Inject(method = "destroyBlock", locals = LocalCapture.CAPTURE_FAILEXCEPTION, at = @At(
value = "INVOKE",
target = "Lnet/minecraft/block/Block;onBroken(Lnet/minecraft/world/IWorld;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)V",
shift = At.Shift.BEFORE
))
private void onBlockBroken(BlockPos blockPos_1, CallbackInfoReturnable<Boolean> cir, BlockState blockState_1, boolean boolean_1)
{
CarpetServer.scriptServer.events.onBlockBroken(player, blockPos_1, blockState_1);
}
}
@@ -3,11 +3,13 @@ package carpet.mixins;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import carpet.fakes.WorldInterface; import carpet.fakes.WorldInterface;
import carpet.utils.SpawnReporter; import carpet.utils.SpawnReporter;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.mob.MobEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BoundingBox; import net.minecraft.util.math.BoundingBox;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes; import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.SpawnHelper; import net.minecraft.world.SpawnHelper;
import net.minecraft.world.World; import net.minecraft.world.World;
@@ -35,13 +37,17 @@ public class SpawnHelperMixin
if (CarpetSettings.b_lagFreeSpawning) if (CarpetSettings.b_lagFreeSpawning)
{ {
BlockPos.Mutable blockpos = new BlockPos.Mutable(); BlockPos.Mutable blockpos = new BlockPos.Mutable();
for (int x = (int)bb.minX, maxx = (int)Math.ceil(bb.maxX); x < maxx; x++) for (int y = (int)bb.minY, maxy = (int)Math.ceil(bb.maxY); y < maxy; y++)
for (int z = (int)bb.minZ, maxz = (int)Math.ceil(bb.maxZ); z < maxz; z++) for (int x = (int)bb.minX, maxx = (int)Math.ceil(bb.maxX); x < maxx; x++)
for (int y = (int)bb.minY, maxy = (int)Math.ceil(bb.maxY); y < maxy; y++) for (int z = (int)bb.minZ, maxz = (int)Math.ceil(bb.maxZ); z < maxz; z++)
{ {
blockpos.set(x, y, z); blockpos.set(x, y, z);
if (world.getBlockState(blockpos).getCollisionShape(world, blockpos) != VoxelShapes.empty()) VoxelShape box = world.getBlockState(blockpos).getCollisionShape(world, blockpos);
return world.doesNotCollide(bb); if ( box == VoxelShapes.empty())
continue;
if (Block.isShapeFullCube(box))
return false;
return world.doesNotCollide(bb);
} }
return true; return true;
} }
@@ -0,0 +1,340 @@
package carpet.script;
import carpet.CarpetServer;
import carpet.script.value.BlockValue;
import carpet.script.value.EntityValue;
import carpet.script.value.ListValue;
import carpet.script.value.NumericValue;
import carpet.script.value.StringValue;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CarpetEventServer
{
public static class Callback
{
public String host;
public String udf;
public Callback(String host, String udf)
{
this.host = host;
this.udf = udf;
}
@Override
public String toString()
{
return udf+((host==null)?"":"(from "+host+")");
}
}
public static class ScheduledCall extends Callback
{
public List<LazyValue> args;
public ServerCommandSource context_source;
public BlockPos context_origin;
public long dueTime;
public ScheduledCall(CarpetContext context, String udf, List<LazyValue> args, long dueTime)
{
super(context.host.getName(), udf);
this.args = args;
this.context_source = context.s;
this.context_origin = context.origin;
this.dueTime = dueTime;
}
public void execute()
{
CarpetServer.scriptServer.runas(context_origin, context_source, host, udf, args);
}
}
public static class CallbackList
{
public List<Callback> callList;
public int reqArgs;
public CallbackList(int reqArgs)
{
this.callList = new ArrayList<>();
this.reqArgs = reqArgs;
}
public void call(Supplier<List<LazyValue>> argumentSupplier, Supplier<ServerCommandSource> cmdSourceSupplier)
{
if (callList.size() > 0)
{
List<LazyValue> argv = argumentSupplier.get(); // empty for onTickDone
ServerCommandSource source = cmdSourceSupplier.get();
assert argv.size() == reqArgs;
callList.removeIf(call -> !CarpetServer.scriptServer.runas(source, call.host, call.udf, argv)); // this actually does the calls
}
}
public boolean addEventCall(String hostName, String funName)
{
ScriptHost host = CarpetServer.scriptServer.getHostByName(hostName);
if (host == null)
{
// impossible call to add
return false;
}
UserDefinedFunction udf = host.globalFunctions.get(funName);
if (udf == null || udf.getArguments().size() != reqArgs)
{
// call won't match arguments
return false;
}
//all clear
//remove duplicates
removeEventCall(hostName, funName);
callList.add(new Callback(hostName, funName));
return true;
}
public void removeEventCall(String hostName, String callName)
{
callList.removeIf((c)-> c.udf.equalsIgnoreCase(callName) && ( hostName == null || c.host.equalsIgnoreCase(hostName) ) );
}
}
public Map<String, CallbackList> eventHandlers = new HashMap<>();
public List<ScheduledCall> scheduledCalls = new LinkedList<>();
public void tick()
{
Iterator<ScheduledCall> eventIterator = scheduledCalls.iterator();
List<ScheduledCall> currentCalls = new ArrayList<>();
while(eventIterator.hasNext())
{
ScheduledCall call = eventIterator.next();
call.dueTime--;
if (call.dueTime <= 0)
{
currentCalls.add(call);
eventIterator.remove();
}
}
for (ScheduledCall call: currentCalls)
{
call.execute();
}
}
public void scheduleCall(CarpetContext context, String function, List<LazyValue> args, long due)
{
scheduledCalls.add(new ScheduledCall(context, function, args, due));
}
public CarpetEventServer()
{
eventHandlers.put("tick",new CallbackList(0));
eventHandlers.put("tick_nether",new CallbackList(0));
eventHandlers.put("tick_ender",new CallbackList(0));
eventHandlers.put("player_jumps",new CallbackList(1));
eventHandlers.put("player_deploys_elytra",new CallbackList(1));
eventHandlers.put("player_wakes_up",new CallbackList(1));
eventHandlers.put("player_rides",new CallbackList(5));
eventHandlers.put("player_uses_item",new CallbackList(3));
eventHandlers.put("player_clicks_block",new CallbackList(3));
eventHandlers.put("player_right_clicks_block",new CallbackList(6));
eventHandlers.put("player_breaks_block",new CallbackList(2));
eventHandlers.put("player_interacts_with_entity",new CallbackList(3));
eventHandlers.put("player_attacks_entity",new CallbackList(2));
eventHandlers.put("player_starts_sneaking",new CallbackList(1));
eventHandlers.put("player_stops_sneaking",new CallbackList(1));
eventHandlers.put("player_starts_sprinting",new CallbackList(1));
eventHandlers.put("player_stops_sprinting",new CallbackList(1));
}
public boolean addEvent(String event, String host, String funName)
{
if (!eventHandlers.containsKey(event))
{
return false;
}
return eventHandlers.get(event).addEventCall(host, funName);
}
public boolean removeEvent(String event, String funName)
{
if (!eventHandlers.containsKey(event))
return false;
Callback callback= decodeCallback(funName);
eventHandlers.get(event).removeEventCall(callback.host, callback.udf);
return true;
}
private Callback decodeCallback(String funName)
{
Pattern find = Pattern.compile("(\\w+)\\(from (\\w+)\\)");
Matcher matcher = find.matcher(funName);
if(matcher.matches())
{
return new Callback(matcher.group(2), matcher.group(1));
}
return new Callback(null, funName);
}
public void onTick()
{
eventHandlers.get("tick").call(Collections::emptyList, CarpetServer.minecraft_server::getCommandSource);
eventHandlers.get("tick_nether").call(Collections::emptyList, () ->
CarpetServer.minecraft_server.getCommandSource().withWorld(CarpetServer.minecraft_server.getWorld(DimensionType.THE_NETHER)));
eventHandlers.get("tick_ender").call(Collections::emptyList, () ->
CarpetServer.minecraft_server.getCommandSource().withWorld(CarpetServer.minecraft_server.getWorld(DimensionType.THE_END)));
}
public void onPlayerJumped(PlayerEntity player)
{
eventHandlers.get("player_jumps").call( () -> Arrays.asList(((c, t) -> new EntityValue(player))), player::getCommandSource);
}
public void onElytraDeploy(ServerPlayerEntity player)
{
eventHandlers.get("player_deploys_elytra").call( () -> Arrays.asList(((c, t) -> new EntityValue(player))), player::getCommandSource);
}
public void onOutOfBed(ServerPlayerEntity player)
{
eventHandlers.get("player_wakes_up").call( () -> Arrays.asList(((c, t) -> new EntityValue(player))), player::getCommandSource);
}
public void onMountControls(PlayerEntity player, float strafeSpeed, float forwardSpeed, boolean jumping, boolean sneaking)
{
eventHandlers.get("player_rides").call( () -> Arrays.asList(
((c, t) -> new EntityValue(player)),
((c, t) -> new NumericValue(forwardSpeed)),
((c, t) -> new NumericValue(strafeSpeed)),
((c, t) -> new NumericValue(jumping)),
((c, t) -> new NumericValue(sneaking))
), player::getCommandSource);
}
public void onRightClick(ServerPlayerEntity player, Hand enumhand)
{
eventHandlers.get("player_uses_item").call( () ->
{
ItemStack itemstack = player.getStackInHand(enumhand);
return Arrays.asList(
((c, t) -> new EntityValue(player)),
((c, t) -> ListValue.of(
new StringValue(Registry.ITEM.getId(itemstack.getItem()).getPath()),
new NumericValue(itemstack.getAmount()),
new StringValue(itemstack.toTag(new CompoundTag()).toString())
)),
((c, t) -> new StringValue(enumhand == Hand.MAIN_HAND ? "mainhand" : "offhand"))
);
}, player::getCommandSource);
}
public void onBlockClicked(ServerPlayerEntity player, BlockPos blockpos, Direction facing)
{
eventHandlers.get("player_clicks_block").call( () -> Arrays.asList(
((c, t) -> new EntityValue(player)),
((c, t) -> new BlockValue(null, player.world, blockpos)),
((c, t) -> new StringValue(facing.getName()))
), player::getCommandSource);
}
public void onRightClickBlock(ServerPlayerEntity player, Hand enumhand, BlockHitResult hitRes)//ItemStack itemstack, Hand enumhand, BlockPos blockpos, Direction enumfacing, Vec3d vec3d)
{
eventHandlers.get("player_right_clicks_block").call( () ->
{
ItemStack itemstack = player.getStackInHand(enumhand);
BlockPos blockpos = hitRes.getBlockPos();
Direction enumfacing = hitRes.getSide();
Vec3d vec3d = hitRes.getPos().subtract(blockpos.getX(), blockpos.getY(), blockpos.getZ());
return Arrays.asList(
((c, t) -> new EntityValue(player)),
((c, t) -> ListValue.of(
new StringValue(Registry.ITEM.getId(itemstack.getItem()).getPath()),
new NumericValue(itemstack.getAmount()),
new StringValue(itemstack.toTag(new CompoundTag()).toString())
)),
((c, t) -> new StringValue(enumhand == Hand.MAIN_HAND ? "mainhand" : "offhand")),
((c, t) -> new BlockValue(null, player.world, blockpos)),
((c, t) -> new StringValue(enumfacing.getName())),
((c, t) -> ListValue.of(
new NumericValue(vec3d.x),
new NumericValue(vec3d.y),
new NumericValue(vec3d.z)
))
);
}, player::getCommandSource);
}
public void onBlockBroken(PlayerEntity player, BlockPos pos, BlockState previousBS)
{
eventHandlers.get("player_breaks_block").call( () -> Arrays.asList(
((c, t) -> new EntityValue(player)),
((c, t) -> new BlockValue(previousBS, player.getEntityWorld(), pos))
), player::getCommandSource);
}
public void onEntityInteracted(ServerPlayerEntity player, Entity entity, Hand enumhand)
{
eventHandlers.get("player_interacts_with_entity").call( () -> Arrays.asList(
((c, t) -> new EntityValue(player)),
((c, t) -> new EntityValue(entity)),
((c, t) -> new StringValue(enumhand==Hand.MAIN_HAND?"mainhand":"offhand"))
), player::getCommandSource);
}
public void onEntityAttacked(ServerPlayerEntity player, Entity entity)
{
eventHandlers.get("player_attacks_entity").call( () -> Arrays.asList(
((c, t) -> new EntityValue(player)),
((c, t) -> new EntityValue(entity))
), player::getCommandSource);
}
public void onStartSneaking(PlayerEntity player)
{
eventHandlers.get("player_starts_sneaking").call( () -> Arrays.asList(((c, t) -> new EntityValue(player))), player::getCommandSource);
}
public void onStopSneaking(PlayerEntity player)
{
eventHandlers.get("player_stops_sneaking").call( () -> Arrays.asList(((c, t) -> new EntityValue(player))), player::getCommandSource);
}
public void onStartSprinting(PlayerEntity player)
{
eventHandlers.get("player_starts_sprinting").call( () -> Arrays.asList(((c, t) -> new EntityValue(player))), player::getCommandSource);
}
public void onStopSprinting(PlayerEntity player)
{
eventHandlers.get("player_stops_sprinting").call( () -> Arrays.asList(((c, t) -> new EntityValue(player))), player::getCommandSource);
}
}
+124 -34
View File
@@ -21,11 +21,16 @@ import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.item.Items;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.command.arguments.ParticleArgumentType; import net.minecraft.command.arguments.ParticleArgumentType;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.client.network.packet.PlaySoundIdS2CPacket; import net.minecraft.client.network.packet.PlaySoundIdS2CPacket;
import net.minecraft.particle.ParticleEffect; import net.minecraft.particle.ParticleEffect;
import net.minecraft.block.BlockPlacementEnvironment; import net.minecraft.block.BlockPlacementEnvironment;
@@ -44,6 +49,8 @@ import net.minecraft.world.LightType;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.Heightmap; import net.minecraft.world.Heightmap;
import net.minecraft.world.loot.context.LootContext;
import net.minecraft.world.loot.context.LootContextParameters;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList; import java.util.ArrayList;
@@ -302,6 +309,12 @@ public class CarpetExpression
* <p>Causes a block to tick at position.</p> * <p>Causes a block to tick at position.</p>
* <h3><code>random_tick(pos)</code></h3> * <h3><code>random_tick(pos)</code></h3>
* <p>Causes a random tick at position.</p> * <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>
* <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>
*
* *
* <h2>Block and World querying</h2> * <h2>Block and World querying</h2>
* *
@@ -518,13 +531,7 @@ public class CarpetExpression
{ {
throw new InternalExpressionException("Block requires at least one parameter"); throw new InternalExpressionException("Block requires at least one parameter");
} }
if (lv.size() == 1) Value retval = BlockValue.fromParams(cc, lv, 0, true).block;
{
Value retval = BlockValue.fromCommandExpression(lv.get(0).evalValue(cc).getString());
return (c_, t_) -> retval;
//return new BlockValue(Registry.field_212618_g.get(new Identifier(lv.get(0).getString())).getDefaultState(), origin);
}
Value retval = BlockValue.fromParams(cc, lv, 0).block;
return (c_, t_) -> retval; return (c_, t_) -> retval;
}); });
@@ -681,36 +688,95 @@ public class CarpetExpression
World world = cc.s.getWorld(); World world = cc.s.getWorld();
if (lv.size() < 2 || lv.size() % 2 == 1) if (lv.size() < 2 || lv.size() % 2 == 1)
throw new InternalExpressionException("set block should have at least 2 params and odd attributes"); throw new InternalExpressionException("set block should have at least 2 params and odd attributes");
BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); BlockValue.LocatorResult targetLocator = BlockValue.fromParams(cc, lv, 0);
Value blockArg = lv.get(locator.offset).evalValue(cc); BlockValue.LocatorResult sourceLocator = BlockValue.fromParams(cc, lv, targetLocator.offset, true);
BlockValue bv = ((blockArg instanceof BlockValue)) ? (BlockValue) blockArg : BlockValue.fromString(blockArg.getString()); BlockState sourceBlockState = sourceLocator.block.getBlockState();
if (bv == BlockValue.NULL) BlockState targetBlockState = world.getBlockState(targetLocator.block.getPos());
throw new InternalExpressionException("block to set to should be a valid block"); if (sourceLocator.offset < lv.size())
BlockState bs = bv.getBlockState();
BlockState targetBlockState = world.getBlockState(locator.block.getPos());
if (lv.size()==1+locator.offset && !(blockArg instanceof BlockValue)) // no reqs for properties
if (targetBlockState.getBlock() == bs.getBlock())
return (c_, t_) -> Value.FALSE;
StateFactory<Block, BlockState> states = bs.getBlock().getStateFactory();
for (int i = 1+locator.offset; i < lv.size(); i += 2)
{ {
String paramString = lv.get(i).evalValue(c).getString(); StateFactory<Block, BlockState> states = sourceBlockState.getBlock().getStateFactory();
Property<?> property = states.getProperty(paramString); for (int i = sourceLocator.offset; i < lv.size(); i += 2)
if (property == null) {
throw new InternalExpressionException("property " + paramString + " doesn't apply to " + blockArg.getString()); String paramString = lv.get(i).evalValue(c).getString();
Property<?> property = states.getProperty(paramString);
String paramValue = lv.get(i + 1).evalValue(c).getString(); if (property == null)
throw new InternalExpressionException("property " + paramString + " doesn't apply to " + sourceLocator.block.getString());
bs = setProperty(property, paramString, paramValue, bs); String paramValue = lv.get(i + 1).evalValue(c).getString();
sourceBlockState = setProperty(property, paramString, paramValue, sourceBlockState);
}
} }
cc.s.getWorld().setBlockState(locator.block.getPos(), bs, 2 | (CarpetSettings.getBool("fillUpdates") ? 0 : 1024)); if (sourceBlockState == targetBlockState)
Value retval = new BlockValue(bs, world, locator.block.getPos()); return (c_, t_) -> Value.FALSE;
if (!CarpetSettings.b_fillUpdates) CarpetSettings.impendingFillSkipUpdates = true;
cc.s.getWorld().setBlockState(targetLocator.block.getPos(), sourceBlockState, 2);
CarpetSettings.impendingFillSkipUpdates = false;
Value retval = new BlockValue(sourceBlockState, world, targetLocator.block.getPos());
return (c_, t_) -> retval; return (c_, t_) -> retval;
}); });
this.expr.addLazyFunction("destroy", -1, (c, t, lv) -> {
CarpetContext cc = (CarpetContext)c;
ServerWorld world = cc.s.getWorld();
BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0);
BlockState state = locator.block.getBlockState();
if (state.isAir())
return (c_, t_) -> Value.FALSE;
BlockPos where = locator.block.getPos();
BlockEntity be = world.getBlockEntity(where);
long how = 0;
if (lv.size() > locator.offset)
how = NumericValue.asNumber(lv.get(locator.offset).evalValue(cc)).getLong();
world.clearBlockState(where, false);
world.playLevelEvent(null, 2001, where, Block.getRawIdFromState(state));
if (how < 0)
{
Block.dropStack(world, where, new ItemStack(state.getBlock()));
}
else
{
ItemStack tool = new ItemStack(Items.DIAMOND_PICKAXE, 1);
tool.addEnchantment(Enchantments.FORTUNE,(int)how);
LootContext.Builder lootContext$Builder_1 = (new LootContext.Builder(world)).
setRandom(world.random).
put(LootContextParameters.POSITION, where).
put(LootContextParameters.BLOCK_STATE, state).
putNullable(LootContextParameters.BLOCK_ENTITY, be).
putNullable(LootContextParameters.THIS_ENTITY, cc.s.getEntity()).
put(LootContextParameters.TOOL, tool);
state.getDroppedStacks(lootContext$Builder_1).forEach((stack) -> Block.dropStack(world, where, stack));
//Block.dropStacks(state, world, where, be, cc.s.getEntity(), tool );
}
return (c_, t_) -> Value.TRUE;
});
this.expr.addLazyFunction("harvest", -1, (c, t, lv) -> {
CarpetContext cc = (CarpetContext)c;
World world = cc.s.getWorld();
Value entityValue = lv.get(0).evalValue(cc);
if (!(entityValue instanceof EntityValue))
return (c_, t_) -> Value.FALSE;
Entity e = ((EntityValue) entityValue).getEntity();
if (!(e instanceof PlayerEntity))
return (c_, t_) -> Value.FALSE;
PlayerEntity player = (PlayerEntity)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.onBlockBroken(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;
});
this.expr.addLazyFunction("blocks_movement", -1, (c, t, lv) -> this.expr.addLazyFunction("blocks_movement", -1, (c, t, lv) ->
booleanStateTest(c, "blocks_movement", lv, (s, p) -> booleanStateTest(c, "blocks_movement", lv, (s, p) ->
!s.canPlaceAtSide(((CarpetContext) c).s.getWorld(), p, BlockPlacementEnvironment.LAND))); !s.canPlaceAtSide(((CarpetContext) c).s.getWorld(), p, BlockPlacementEnvironment.LAND)));
@@ -891,7 +957,7 @@ public class CarpetExpression
* <p>Returns triple of short name, stack count, and NBT of item held in <code>slot</code>. * <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> * Available options for <code>slot</code> are:</p>
* <ul> * <ul>
* <li><code>main</code></li> * <li><code>mainhand</code></li>
* <li><code>offhand</code></li> * <li><code>offhand</code></li>
* <li><code>head</code></li> * <li><code>head</code></li>
* <li><code>chest</code></li> * <li><code>chest</code></li>
@@ -1573,6 +1639,9 @@ public class CarpetExpression
* </pre> * </pre>
* <h3><code>current_dimension()</code></h3> * <h3><code>current_dimension()</code></h3>
* <p>Returns current dimension that scripts run in.</p> * <p>Returns current dimension that scripts run in.</p>
* <h3><code>schedule(delay, function, args...)</code></h3>
* <p>Schedules a user defined function to run with a specified <code>delay</code> ticks of delay.
* Scheduled functions run at the end of the tick, and they will run in order they were scheduled.</p>
* <h3><code>plop(pos, what)</code></h3> * <h3><code>plop(pos, what)</code></h3>
* <p>Plops a structure or a feature at a given <code>pos</code>, so block, triple position coordinates * <p>Plops a structure or a feature at a given <code>pos</code>, so block, triple position coordinates
* or a list of coordinates. To <code>what</code> gets plopped and exactly where it often depends on the * or a list of coordinates. To <code>what</code> gets plopped and exactly where it often depends on the
@@ -1816,7 +1885,7 @@ public class CarpetExpression
} }
else else
{ {
Messenger.m(s, "w "); Messenger.m(s, "w "+ lv.get(0).evalValue(c).getString());
} }
return lv.get(0); // pass through for variables return lv.get(0); // pass through for variables
}); });
@@ -1885,6 +1954,27 @@ public class CarpetExpression
return (c_, t_) -> Value.NULL; return (c_, t_) -> Value.NULL;
return (c_, t_) -> new NumericValue(res); return (c_, t_) -> new NumericValue(res);
}); });
this.expr.addLazyFunction("schedule", -1, (c, t, lv) -> {
if (lv.size()<2)
throw new InternalExpressionException("schedule should have at least 2 arguments, delay and call name");
Long delay = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong();
String funname = lv.get(1).evalValue(c).getString();
CarpetContext cc = (CarpetContext)c;
if (!cc.host.globalFunctions.containsKey(funname))
throw new InternalExpressionException("function "+funname+" is not defined");
List<LazyValue> args = new ArrayList<>();
for (int i=2; i < lv.size(); i++)
{
Value arg = lv.get(i).evalValue(cc);
args.add( (_c, _t) -> arg);
}
if (cc.host.globalFunctions.get(funname).getArguments().size() != args.size())
throw new InternalExpressionException("function "+funname+" takes "+
cc.host.globalFunctions.get(funname).getArguments().size()+" arguments, "+args.size()+" provided.");
CarpetServer.scriptServer.events.scheduleCall(cc, funname, args, delay);
return (c_, t_) -> Value.TRUE;
});
} }
/** /**
@@ -7,6 +7,7 @@ import carpet.script.bundled.FileModule;
import carpet.script.bundled.ModuleInterface; import carpet.script.bundled.ModuleInterface;
import carpet.script.exception.CarpetExpressionException; import carpet.script.exception.CarpetExpressionException;
import carpet.script.exception.ExpressionException; import carpet.script.exception.ExpressionException;
import carpet.script.exception.InvalidCallbackException;
import carpet.script.value.Value; import carpet.script.value.Value;
import carpet.utils.Messenger; import carpet.utils.Messenger;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
@@ -36,6 +37,7 @@ public class CarpetScriptServer
long tickStart; long tickStart;
public boolean stopAll; public boolean stopAll;
Set<String> holyMoly; Set<String> holyMoly;
public CarpetEventServer events;
public static List<ModuleInterface> bundledModuleData = new ArrayList<ModuleInterface>(){{ public static List<ModuleInterface> bundledModuleData = new ArrayList<ModuleInterface>(){{
add(new CameraPathModule()); add(new CameraPathModule());
@@ -43,7 +45,8 @@ public class CarpetScriptServer
public CarpetScriptServer() public CarpetScriptServer()
{ {
globalHost = createMinecraftScriptHost(""); globalHost = createMinecraftScriptHost(null);
events = new CarpetEventServer();
modules = new HashMap<>(); modules = new HashMap<>();
tickStart = 0L; tickStart = 0L;
stopAll = false; stopAll = false;
@@ -102,6 +105,13 @@ public class CarpetScriptServer
return moduleNames; return moduleNames;
} }
public ScriptHost getHostByName(String name)
{
if (name == null)
return globalHost;
return modules.get(name);
}
private static ScriptHost createMinecraftScriptHost(String name) private static ScriptHost createMinecraftScriptHost(String name)
{ {
@@ -146,11 +156,31 @@ public class CarpetScriptServer
} }
modules.put(name, newHost); modules.put(name, newHost);
addEvents(source, name);
addCommand(source, name); addCommand(source, name);
return true; return true;
} }
public void addEvents(ServerCommandSource source, String hostName)
{
ScriptHost host = modules.get(hostName);
if (host == null)
{
return;
}
for (String fun : host.globalFunctions.keySet())
{
if (!fun.startsWith("__on_"))
continue;
String event = fun.replaceFirst("__on_","");
if (!events.eventHandlers.containsKey(event))
continue;
events.addEvent(event, hostName, fun);
}
}
public void addCommand(ServerCommandSource source, String hostName) public void addCommand(ServerCommandSource source, String hostName)
{ {
@@ -278,4 +308,25 @@ public class CarpetScriptServer
Messenger.m(source, "w Removed host "+name); Messenger.m(source, "w Removed host "+name);
return true; return true;
} }
public boolean runas(ServerCommandSource source, String hostname, String udf_name, List<LazyValue> argv)
{
return runas(BlockPos.ORIGIN, source, hostname, udf_name, argv);
}
public boolean runas(BlockPos origin, ServerCommandSource source, String hostname, String udf_name, List<LazyValue> argv)
{
ScriptHost host = globalHost;
if (hostname != null)
host = modules.get(hostname);
try
{
host.callUDF(origin, source, host.globalFunctions.get(udf_name), argv);
}
catch (NullPointerException | InvalidCallbackException npe)
{
return false;
}
return true;
}
} }
+28 -1
View File
@@ -1,7 +1,9 @@
package carpet.script; package carpet.script;
import carpet.CarpetServer; import carpet.CarpetServer;
import carpet.CarpetSettings;
import carpet.script.exception.ExpressionException; import carpet.script.exception.ExpressionException;
import carpet.script.exception.InvalidCallbackException;
import carpet.script.value.NumericValue; import carpet.script.value.NumericValue;
import carpet.script.value.StringValue; import carpet.script.value.StringValue;
import carpet.script.value.Value; import carpet.script.value.Value;
@@ -28,7 +30,7 @@ public class ScriptHost
private String name; private String name;
public String getName() {return name;} public String getName() {return name;}
public ScriptHost(String name) ScriptHost(String name)
{ {
this.name = name; this.name = name;
globalVariables.put("euler", (c, t) -> Expression.euler); globalVariables.put("euler", (c, t) -> Expression.euler);
@@ -155,4 +157,29 @@ public class ScriptHost
return e.getMessage(); return e.getMessage();
} }
} }
public void callUDF(BlockPos pos, ServerCommandSource source, UserDefinedFunction acf, List<LazyValue> argv) throws InvalidCallbackException
{
if (CarpetServer.scriptServer.stopAll)
return;
List<String> args = acf.getArguments();
if (argv.size() != args.size())
{
throw new InvalidCallbackException();
}
try
{
// TODO: this is just for now - invoke would be able to invoke other hosts scripts
Context context = new CarpetContext(this, source, pos);
Expression.evalValue(
() -> acf.lazyEval(context, Context.VOID, acf.expression, acf.token, argv),
context,
Context.VOID);
}
catch (ExpressionException e)
{
CarpetSettings.LOG.error("Callback failed: "+e.getMessage());
}
}
} }
@@ -0,0 +1,5 @@
package carpet.script.exception;
public class InvalidCallbackException extends Exception
{
}
@@ -33,26 +33,8 @@ public class BlockValue extends Value
return new BlockValue(null, c.s.getWorld(), pos); return new BlockValue(null, c.s.getWorld(), pos);
} }
public static BlockValue fromString(String str)
{
try
{
Identifier blockId = Identifier.fromCommandInput(new StringReader(str));
if (Registry.BLOCK.containsId(blockId))
{
Block block = Registry.BLOCK.get(blockId);
return new BlockValue(block.getDefaultState(), null, null);
}
}
catch (CommandSyntaxException ignored)
{
}
throw new InternalExpressionException("Unknown block: "+str);
}
private static Map<String, BlockValue> bvCache= new HashMap<>(); private static Map<String, BlockValue> bvCache= new HashMap<>();
public static BlockValue fromCommandExpression(String str) public static BlockValue fromString(String str)
{ {
try try
{ {
@@ -62,6 +44,8 @@ public class BlockValue extends Value
if (blockstateparser.getBlockState() != null) if (blockstateparser.getBlockState() != null)
{ {
bv = new BlockValue(blockstateparser.getBlockState(), null, null); bv = new BlockValue(blockstateparser.getBlockState(), null, null);
if (bvCache.size()>10000)
bvCache.clear();
bvCache.put(str, bv); bvCache.put(str, bv);
return bv; return bv;
} }
@@ -110,10 +94,20 @@ public class BlockValue extends Value
} }
public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset) public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset)
{
return fromParams(c, params,offset, false);
}
public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset, boolean acceptString)
{ {
try try
{ {
Value v1 = params.get(0 + offset).evalValue(c); Value v1 = params.get(0 + offset).evalValue(c);
//add conditional from string name
if (acceptString && v1 instanceof StringValue)
{
return new LocatorResult(fromString(v1.getString()), 1+offset);
}
if (v1 instanceof BlockValue) if (v1 instanceof BlockValue)
{ {
return new LocatorResult(((BlockValue) v1), 1+offset); return new LocatorResult(((BlockValue) v1), 1+offset);
@@ -131,7 +131,7 @@ public class EntityValue extends Value
return featureAccessors.get(what).apply(entity, arg); return featureAccessors.get(what).apply(entity, arg);
} }
private static Map<String, EquipmentSlot> inventorySlots = new HashMap<String, EquipmentSlot>(){{ private static Map<String, EquipmentSlot> inventorySlots = new HashMap<String, EquipmentSlot>(){{
put("main", EquipmentSlot.MAINHAND); put("mainhand", EquipmentSlot.MAINHAND);
put("offhand", EquipmentSlot.OFFHAND); put("offhand", EquipmentSlot.OFFHAND);
put("head", EquipmentSlot.HEAD); put("head", EquipmentSlot.HEAD);
put("chest", EquipmentSlot.CHEST); put("chest", EquipmentSlot.CHEST);
+2
View File
@@ -48,6 +48,8 @@
"FossilFeatureMixin", "FossilFeatureMixin",
"BuriedTreasureGeneratorPieceMixin", "BuriedTreasureGeneratorPieceMixin",
"GravityStructureProcessorMixin", "GravityStructureProcessorMixin",
"ServerPlayNetworkHandler_scarpetEventsMixin",
"ServerPlayerInteractionManager_scarpetEventsMixin",
"ServerChunkManagerMixin", "ServerChunkManagerMixin",