Merge branch 'master' into 1.15
# Conflicts: # src/main/java/carpet/script/CarpetExpression.java
This commit is contained in:
commit
3e6f83905c
21 files changed
+1019
-296
No files matched your search
@@ -21,6 +21,7 @@ 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.chunk.WorldChunk;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -129,15 +130,24 @@ public class BlockValue extends Value
|
||||
|
||||
public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset)
|
||||
{
|
||||
return fromParams(c, params,offset, false);
|
||||
return fromParams(c, params,offset, false, false);
|
||||
}
|
||||
|
||||
public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset, boolean acceptString)
|
||||
{
|
||||
return fromParams(c, params,offset, acceptString, false);
|
||||
}
|
||||
|
||||
public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset, boolean acceptString, boolean optional)
|
||||
{
|
||||
try
|
||||
{
|
||||
Value v1 = params.get(0 + offset).evalValue(c);
|
||||
//add conditional from string name
|
||||
if (optional && v1 instanceof NullValue)
|
||||
{
|
||||
return new LocatorResult(null, 1+offset);
|
||||
}
|
||||
if (acceptString && v1 instanceof StringValue)
|
||||
{
|
||||
return new LocatorResult(fromString(v1.getString()), 1+offset);
|
||||
@@ -192,6 +202,15 @@ public class BlockValue extends Value
|
||||
throw new InternalExpressionException("Attempted to fetch block state without world or stored block state");
|
||||
}
|
||||
|
||||
public static BlockEntity getBlockEntity(ServerWorld world, BlockPos pos)
|
||||
{
|
||||
if (world.getServer().isOnThread())
|
||||
return world.getBlockEntity(pos);
|
||||
else
|
||||
return world.getWorldChunk(pos).getBlockEntity(pos, WorldChunk.CreationType.IMMEDIATE);
|
||||
}
|
||||
|
||||
|
||||
public CompoundTag getData()
|
||||
{
|
||||
if (data != null)
|
||||
@@ -202,7 +221,7 @@ public class BlockValue extends Value
|
||||
}
|
||||
if (world != null && pos != null)
|
||||
{
|
||||
BlockEntity be = world.getBlockEntity(pos);
|
||||
BlockEntity be = getBlockEntity(world, pos);
|
||||
CompoundTag tag = new CompoundTag();
|
||||
if (be == null)
|
||||
{
|
||||
|
||||
@@ -223,7 +223,7 @@ public class EntityValue extends Value
|
||||
put("dimension", (e, a) -> new StringValue(nameFromRegistryId(Registry.DIMENSION.getId(e.dimension))));
|
||||
put("height", (e, a) -> new NumericValue(e.getDimensions(EntityPose.STANDING).height));
|
||||
put("width", (e, a) -> new NumericValue(e.getDimensions(EntityPose.STANDING).width));
|
||||
put("eye_height", (e, a) -> new NumericValue(e.getEyeHeight(EntityPose.STANDING)));
|
||||
put("eye_height", (e, a) -> new NumericValue(e.getStandingEyeHeight()));
|
||||
put("age", (e, a) -> new NumericValue(e.age));
|
||||
put("despawn_timer", (e, a) -> e instanceof LivingEntity?new NumericValue(((LivingEntity) e).getDespawnCounter()):Value.NULL);
|
||||
put("item", (e, a) -> (e instanceof ItemEntity)?ListValue.fromItemStack(((ItemEntity) e).getStack()):Value.NULL);
|
||||
@@ -273,6 +273,22 @@ public class EntityValue extends Value
|
||||
}
|
||||
return Value.NULL;
|
||||
});
|
||||
|
||||
put("permission_level", (e, a) -> {
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
{
|
||||
ServerPlayerEntity spe = (ServerPlayerEntity) e;
|
||||
for (int i=4; i>=0; i--)
|
||||
{
|
||||
if (spe.allowsPermissionLevel(i))
|
||||
return new NumericValue(i);
|
||||
|
||||
}
|
||||
return new NumericValue(0);
|
||||
}
|
||||
return Value.NULL;
|
||||
});
|
||||
|
||||
//spectating_entity
|
||||
// isGlowing
|
||||
put("effect", (e, a) ->
|
||||
@@ -743,6 +759,39 @@ public class EntityValue extends Value
|
||||
else
|
||||
e.noClip = v.getBoolean();
|
||||
});
|
||||
put("effect", (e, v) ->
|
||||
{
|
||||
if (!(e instanceof LivingEntity)) return;
|
||||
LivingEntity le = (LivingEntity)e;
|
||||
if (v == null)
|
||||
le.clearPotionEffects();
|
||||
else if (v instanceof ListValue)
|
||||
{
|
||||
List<Value> lv = ((ListValue) v).getItems();
|
||||
if (lv.size() >= 2 && lv.size() <= 5)
|
||||
{
|
||||
String effectName = lv.get(0).getString();
|
||||
if (effectName.startsWith("minecraft:"))
|
||||
effectName = "minecraft:"+effectName;
|
||||
StatusEffect effect = Registry.STATUS_EFFECT.get(new Identifier(effectName));
|
||||
if (effect == null)
|
||||
throw new InternalExpressionException("Wrong effect name: "+effectName);
|
||||
int duration = (int)NumericValue.asNumber(lv.get(1)).getLong();
|
||||
int amplifier = 0;
|
||||
if (lv.size() > 2)
|
||||
amplifier = (int)NumericValue.asNumber(lv.get(2)).getLong();
|
||||
boolean showParticles = true;
|
||||
if (lv.size() > 3)
|
||||
showParticles = lv.get(3).getBoolean();
|
||||
boolean showIcon = true;
|
||||
if (lv.size() > 4)
|
||||
showIcon = lv.get(4).getBoolean();
|
||||
le.addPotionEffect(new StatusEffectInstance(effect, duration, amplifier, showParticles, showIcon));
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new InternalExpressionException("'effect' needs either no arguments (clear) or effect name, duration, and optional amplifier, show particles and show icon");
|
||||
});
|
||||
|
||||
// gamemode
|
||||
// spectate
|
||||
|
||||
@@ -246,7 +246,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
||||
return items;
|
||||
}
|
||||
|
||||
public Iterator<Value> iterator() { return new ArrayList<>(items).iterator(); }
|
||||
public Iterator<Value> iterator() { return new ArrayList<>(items).iterator(); } // should be thread safe
|
||||
|
||||
public void extend(List<Value> subList)
|
||||
{
|
||||
|
||||
@@ -5,6 +5,12 @@ import carpet.script.LazyValue;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ChestBlock;
|
||||
import net.minecraft.block.InventoryProvider;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.ChestBlockEntity;
|
||||
import net.minecraft.block.entity.HopperBlockEntity;
|
||||
import net.minecraft.command.arguments.ItemStackArgument;
|
||||
import net.minecraft.command.arguments.ItemStringReader;
|
||||
@@ -21,8 +27,12 @@ import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.StringNbtReader;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -116,6 +126,41 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
return copy;
|
||||
}
|
||||
|
||||
// stolen from HopperBlockEntity, adjusted for threaded operation
|
||||
public static Inventory getInventoryAt(ServerWorld world, BlockPos blockPos)
|
||||
{
|
||||
Inventory inventory = null;
|
||||
BlockState blockState = world.getBlockState(blockPos);
|
||||
Block block = blockState.getBlock();
|
||||
if (block instanceof InventoryProvider) {
|
||||
inventory = ((InventoryProvider)block).getInventory(blockState, world, blockPos);
|
||||
} else if (block.hasBlockEntity()) {
|
||||
BlockEntity blockEntity = BlockValue.getBlockEntity(world, blockPos);
|
||||
if (blockEntity instanceof Inventory) {
|
||||
inventory = (Inventory)blockEntity;
|
||||
if (inventory instanceof ChestBlockEntity && block instanceof ChestBlock) {
|
||||
inventory = ChestBlock.getInventory(blockState, world, blockPos, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inventory == null) {
|
||||
List<Entity> list = world.getEntities(
|
||||
(Entity)null,
|
||||
new Box(
|
||||
blockPos.getX() - 0.5D, blockPos.getY() - 0.5D, blockPos.getZ() - 0.5D,
|
||||
blockPos.getX() + 0.5D, blockPos.getY() + 0.5D, blockPos.getZ() + 0.5D),
|
||||
EntityPredicates.VALID_INVENTORIES
|
||||
);
|
||||
if (!list.isEmpty()) {
|
||||
inventory = (Inventory)list.get(world.random.nextInt(list.size()));
|
||||
}
|
||||
}
|
||||
|
||||
return inventory;
|
||||
}
|
||||
|
||||
|
||||
public static InventoryLocator locateInventory(CarpetContext c, List<LazyValue> params, int offset)
|
||||
{
|
||||
try
|
||||
@@ -139,7 +184,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
BlockPos pos = ((BlockValue) v1).getPos();
|
||||
if (pos == null)
|
||||
throw new InternalExpressionException("Block to access inventory needs to be positioned in the world");
|
||||
inv = HopperBlockEntity.getInventoryAt(c.s.getWorld(), pos);
|
||||
inv = getInventoryAt(c.s.getWorld(), pos);
|
||||
if (inv == null)
|
||||
return null;
|
||||
return new InventoryLocator(pos, pos, inv, offset + 1);
|
||||
@@ -151,7 +196,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
NumericValue.asNumber(args.get(0)).getDouble(),
|
||||
NumericValue.asNumber(args.get(1)).getDouble(),
|
||||
NumericValue.asNumber(args.get(2)).getDouble());
|
||||
inv = HopperBlockEntity.getInventoryAt(c.s.getWorld(), pos);
|
||||
inv = getInventoryAt(c.s.getWorld(), pos);
|
||||
if (inv == null)
|
||||
return null;
|
||||
return new InventoryLocator(pos, pos, inv, offset + 1);
|
||||
@@ -160,7 +205,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
NumericValue.asNumber(v1).getDouble(),
|
||||
NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(),
|
||||
NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble());
|
||||
inv = HopperBlockEntity.getInventoryAt(c.s.getWorld(), pos);
|
||||
inv = getInventoryAt(c.s.getWorld(), pos);
|
||||
if (inv == null)
|
||||
return null;
|
||||
return new InventoryLocator(pos, pos, inv, offset + 3);
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.Context;
|
||||
import carpet.script.Expression;
|
||||
import carpet.script.LazyValue;
|
||||
import carpet.script.Tokenizer;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
public class ThreadValue extends Value
|
||||
{
|
||||
private CompletableFuture<Value> taskFuture;
|
||||
private long id;
|
||||
private static long sequence = 0L;
|
||||
private static final Map<Value,ThreadPoolExecutor> executorServices = new HashMap<>();
|
||||
|
||||
public ThreadValue(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List<LazyValue> args)
|
||||
{
|
||||
id = sequence++;
|
||||
taskFuture = CompletableFuture.supplyAsync(
|
||||
() -> function.lazyEval(ctx, Context.NONE, expr, token, args).evalValue(ctx),
|
||||
executorServices.computeIfAbsent(pool, (v) -> (ThreadPoolExecutor)Executors.newCachedThreadPool())
|
||||
);
|
||||
Thread.yield();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
return taskFuture.getNow(Value.NULL).getString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean()
|
||||
{
|
||||
return taskFuture.getNow(Value.NULL).getBoolean();
|
||||
}
|
||||
|
||||
public Value join()
|
||||
{
|
||||
try
|
||||
{
|
||||
return taskFuture.get();
|
||||
}
|
||||
catch (InterruptedException | ExecutionException e)
|
||||
{
|
||||
return Value.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFinished()
|
||||
{
|
||||
return taskFuture.isDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (!(o instanceof ThreadValue))
|
||||
return false;
|
||||
return ((ThreadValue) o).id == this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Value o)
|
||||
{
|
||||
if (!(o instanceof ThreadValue))
|
||||
throw new InternalExpressionException("Cannot compare tasks to other types");
|
||||
return (int) (this.id - ((ThreadValue) o).id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Long.hashCode(id);
|
||||
}
|
||||
|
||||
public static int taskCount()
|
||||
{
|
||||
return executorServices.values().stream().map(ThreadPoolExecutor::getActiveCount).reduce(0, Integer::sum);
|
||||
}
|
||||
|
||||
public static int taskCount(Value pool)
|
||||
{
|
||||
if (executorServices.containsKey(pool))
|
||||
{
|
||||
return executorServices.get(pool).getActiveCount();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -110,7 +110,7 @@ public abstract class Value implements Comparable<Value>, Cloneable
|
||||
@Override
|
||||
public int compareTo(final Value o)
|
||||
{
|
||||
if (o instanceof NumericValue || o instanceof ListValue)
|
||||
if (o instanceof NumericValue || o instanceof ListValue || o instanceof ThreadValue)
|
||||
{
|
||||
return -o.compareTo(this);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user