semi-auto cleanup

This commit is contained in:
gnembon committed 2023-02-04 13:26:21 +01:00
1 parent cad80f82c6
commit 8f61271606
99 files changed
+11463 -8007

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -15,9 +15,11 @@ import carpet.script.value.LazyListValue;
import carpet.script.value.ListValue;
import carpet.script.value.NumericValue;
import carpet.script.value.Value;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.server.level.ServerLevel;
@@ -27,19 +29,23 @@ import static java.lang.Math.abs;
import static java.lang.Math.max;
import static java.lang.Math.min;
public class BlockIterators {
public static void apply(Expression expression)
public class BlockIterators
{
public static void apply(final Expression expression)
{
// lazy cause of lazy expression
expression.addLazyFunction("scan", (c, t, llv) ->
{
if (llv.size() < 3) throw new InternalExpressionException("'scan' needs many more arguments");
List<Value> lv = Fluff.AbstractFunction.unpackLazy(llv.subList(0, llv.size()-1), c, Context.NONE);
CarpetContext cc = (CarpetContext)c;
BlockArgument centerLocator = BlockArgument.findIn(cc, lv, 0);
if (llv.size() < 3)
{
throw new InternalExpressionException("'scan' needs many more arguments");
}
final List<Value> lv = Fluff.AbstractFunction.unpackLazy(llv.subList(0, llv.size() - 1), c, Context.NONE);
final CarpetContext cc = (CarpetContext) c;
final BlockArgument centerLocator = BlockArgument.findIn(cc, lv, 0);
Vector3Argument rangeLocator = Vector3Argument.findIn(lv, centerLocator.offset);
BlockPos center = centerLocator.block.getPos();
Vec3i range;
final BlockPos center = centerLocator.block.getPos();
final Vec3i range;
if (rangeLocator.fromBlock)
{
@@ -48,14 +54,13 @@ public class BlockIterators {
abs(rangeLocator.vec.y - center.getY()),
abs(rangeLocator.vec.z - center.getZ())
);
//if (lv.size() > rangeLocator.offset+1) throw new InternalExpressionException("'scan' takes two block positions, and the expression")
}
else
{
range = new Vec3i(abs(rangeLocator.vec.x), abs(rangeLocator.vec.y), abs(rangeLocator.vec.z));
}
Vec3i upperRange = range;
if (lv.size() > rangeLocator.offset+1) // +1 cause we still need the expression
if (lv.size() > rangeLocator.offset + 1) // +1 cause we still need the expression
{
rangeLocator = Vector3Argument.findIn(lv, rangeLocator.offset);
if (rangeLocator.fromBlock)
@@ -65,60 +70,60 @@ public class BlockIterators {
abs(rangeLocator.vec.y - center.getY()),
abs(rangeLocator.vec.z - center.getZ())
);
//if (lv.size() > rangeLocator.offset+1) throw new InternalExpressionException("'scan' takes two block positions, and the expression")
}
else
{
upperRange = new Vec3i(abs(rangeLocator.vec.x), abs(rangeLocator.vec.y), abs(rangeLocator.vec.z));
}
}
if (llv.size() != rangeLocator.offset+1)
if (llv.size() != rangeLocator.offset + 1)
{
throw new InternalExpressionException("'scan' takes two, or three block positions, and an expression: "+lv.size()+" "+rangeLocator.offset);
throw new InternalExpressionException("'scan' takes two, or three block positions, and an expression: " + lv.size() + " " + rangeLocator.offset);
}
LazyValue expr = llv.get(rangeLocator.offset);
final LazyValue expr = llv.get(rangeLocator.offset);
int cx = center.getX();
int cy = center.getY();
int cz = center.getZ();
int xrange = range.getX();
int yrange = range.getY();
int zrange = range.getZ();
int xprange = upperRange.getX();
int yprange = upperRange.getY();
int zprange = upperRange.getZ();
final int cx = center.getX();
final int cy = center.getY();
final int cz = center.getZ();
final int xrange = range.getX();
final int yrange = range.getY();
final int zrange = range.getZ();
final int xprange = upperRange.getX();
final int yprange = upperRange.getY();
final int zprange = upperRange.getZ();
//saving outer scope
LazyValue _x = c.getVariable("_x");
LazyValue _y = c.getVariable("_y");
LazyValue _z = c.getVariable("_z");
LazyValue __ = c.getVariable("_");
final LazyValue _x = c.getVariable("_x");
final LazyValue _y = c.getVariable("_y");
final LazyValue _z = c.getVariable("_z");
final LazyValue __ = c.getVariable("_");
int sCount = 0;
outer:for (int y=cy-yrange; y <= cy+yprange; y++)
outer:
for (int y = cy - yrange; y <= cy + yprange; y++)
{
int yFinal = y;
final int yFinal = y;
c.setVariable("_y", (c_, t_) -> new NumericValue(yFinal).bindTo("_y"));
for (int x=cx-xrange; x <= cx+xprange; x++)
for (int x = cx - xrange; x <= cx + xprange; x++)
{
int xFinal = x;
final int xFinal = x;
c.setVariable("_x", (c_, t_) -> new NumericValue(xFinal).bindTo("_x"));
for (int z=cz-zrange; z <= cz+zprange; z++)
for (int z = cz - zrange; z <= cz + zprange; z++)
{
int zFinal = z;
final int zFinal = z;
c.setVariable("_z", (c_, t_) -> new NumericValue(zFinal).bindTo("_z"));
Value blockValue = BlockValue.fromCoords(((CarpetContext)c), xFinal,yFinal,zFinal).bindTo("_");
c.setVariable( "_", (cc_, t_c) -> blockValue);
final Value blockValue = BlockValue.fromCoords(((CarpetContext) c), xFinal, yFinal, zFinal).bindTo("_");
c.setVariable("_", (cc_, t_c) -> blockValue);
Value result;
try
{
result = expr.evalValue(c, t);
}
catch (ContinueStatement notIgnored)
catch (final ContinueStatement notIgnored)
{
result = notIgnored.retval;
}
catch (BreakStatement notIgnored)
catch (final BreakStatement notIgnored)
{
break outer;
}
@@ -134,66 +139,70 @@ public class BlockIterators {
c.setVariable("_y", _y);
c.setVariable("_z", _z);
c.setVariable("_", __);
int finalSCount = sCount;
final int finalSCount = sCount;
return (c_, t_) -> new NumericValue(finalSCount);
});
// must be lazy
expression.addLazyFunction("volume", (c, t, llv) ->
{
CarpetContext cc = (CarpetContext)c;
if (llv.size() < 3) throw new InternalExpressionException("'volume' needs many more arguments");
List<Value> lv = Fluff.AbstractFunction.unpackLazy(llv.subList(0, llv.size()-1), c, Context.NONE);
final CarpetContext cc = (CarpetContext) c;
if (llv.size() < 3)
{
throw new InternalExpressionException("'volume' needs many more arguments");
}
final List<Value> lv = Fluff.AbstractFunction.unpackLazy(llv.subList(0, llv.size() - 1), c, Context.NONE);
BlockArgument pos1Locator = BlockArgument.findIn(cc, lv, 0);
BlockArgument pos2Locator = BlockArgument.findIn(cc, lv, pos1Locator.offset);
BlockPos pos1 = pos1Locator.block.getPos();
BlockPos pos2 = pos2Locator.block.getPos();
final BlockArgument pos1Locator = BlockArgument.findIn(cc, lv, 0);
final BlockArgument pos2Locator = BlockArgument.findIn(cc, lv, pos1Locator.offset);
final BlockPos pos1 = pos1Locator.block.getPos();
final BlockPos pos2 = pos2Locator.block.getPos();
int x1 = pos1.getX();
int y1 = pos1.getY();
int z1 = pos1.getZ();
int x2 = pos2.getX();
int y2 = pos2.getY();
int z2 = pos2.getZ();
int minx = min(x1, x2);
int miny = min(y1, y2);
int minz = min(z1, z2);
int maxx = max(x1, x2);
int maxy = max(y1, y2);
int maxz = max(z1, z2);
LazyValue expr = llv.get(pos2Locator.offset);
final int x1 = pos1.getX();
final int y1 = pos1.getY();
final int z1 = pos1.getZ();
final int x2 = pos2.getX();
final int y2 = pos2.getY();
final int z2 = pos2.getZ();
final int minx = min(x1, x2);
final int miny = min(y1, y2);
final int minz = min(z1, z2);
final int maxx = max(x1, x2);
final int maxy = max(y1, y2);
final int maxz = max(z1, z2);
final LazyValue expr = llv.get(pos2Locator.offset);
//saving outer scope
LazyValue _x = c.getVariable("_x");
LazyValue _y = c.getVariable("_y");
LazyValue _z = c.getVariable("_z");
LazyValue __ = c.getVariable("_");
final LazyValue _x = c.getVariable("_x");
final LazyValue _y = c.getVariable("_y");
final LazyValue _z = c.getVariable("_z");
final LazyValue __ = c.getVariable("_");
int sCount = 0;
outer:for (int y=miny; y <= maxy; y++)
outer:
for (int y = miny; y <= maxy; y++)
{
int yFinal = y;
final int yFinal = y;
c.setVariable("_y", (c_, t_) -> new NumericValue(yFinal).bindTo("_y"));
for (int x=minx; x <= maxx; x++)
for (int x = minx; x <= maxx; x++)
{
int xFinal = x;
final int xFinal = x;
c.setVariable("_x", (c_, t_) -> new NumericValue(xFinal).bindTo("_x"));
for (int z=minz; z <= maxz; z++)
for (int z = minz; z <= maxz; z++)
{
int zFinal = z;
final int zFinal = z;
c.setVariable("_z", (c_, t_) -> new NumericValue(zFinal).bindTo("_z"));
Value blockValue = BlockValue.fromCoords(((CarpetContext)c), xFinal,yFinal,zFinal).bindTo("_");
c.setVariable( "_", (cc_, t_c) -> blockValue);
final Value blockValue = BlockValue.fromCoords(((CarpetContext) c), xFinal, yFinal, zFinal).bindTo("_");
c.setVariable("_", (cc_, t_c) -> blockValue);
Value result;
try
{
result = expr.evalValue(c, t);
}
catch (ContinueStatement notIgnored)
catch (final ContinueStatement notIgnored)
{
result = notIgnored.retval;
}
catch (BreakStatement notIgnored)
catch (final BreakStatement notIgnored)
{
break outer;
}
@@ -209,16 +218,16 @@ public class BlockIterators {
c.setVariable("_y", _y);
c.setVariable("_z", _z);
c.setVariable("_", __);
int finalSCount = sCount;
final int finalSCount = sCount;
return (c_, t_) -> new NumericValue(finalSCount);
});
expression.addContextFunction("neighbours", -1, (c, t, lv)->
expression.addContextFunction("neighbours", -1, (c, t, lv) ->
{
BlockPos center = BlockArgument.findIn((CarpetContext) c, lv,0).block.getPos();
ServerLevel world = ((CarpetContext) c).level();
final BlockPos center = BlockArgument.findIn((CarpetContext) c, lv, 0).block.getPos();
final ServerLevel world = ((CarpetContext) c).level();
List<Value> neighbours = new ArrayList<>();
final List<Value> neighbours = new ArrayList<>();
neighbours.add(new BlockValue(null, world, center.above()));
neighbours.add(new BlockValue(null, world, center.below()));
neighbours.add(new BlockValue(null, world, center.north()));
@@ -228,20 +237,26 @@ public class BlockIterators {
return ListValue.wrap(neighbours);
});
expression.addContextFunction("rect", -1, (c, t, lv)->
expression.addContextFunction("rect", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext) c;
int cx, cy, cz;
int sminx, sminy, sminz;
int smaxx, smaxy, smaxz;
BlockArgument cposLocator = BlockArgument.findIn(cc, lv, 0);
BlockPos cpos = cposLocator.block.getPos();
final CarpetContext cc = (CarpetContext) c;
final int cx;
final int cy;
final int cz;
final int sminx;
final int sminy;
final int sminz;
final int smaxx;
final int smaxy;
final int smaxz;
final BlockArgument cposLocator = BlockArgument.findIn(cc, lv, 0);
final BlockPos cpos = cposLocator.block.getPos();
cx = cpos.getX();
cy = cpos.getY();
cz = cpos.getZ();
if (lv.size() > cposLocator.offset)
{
Vector3Argument diffLocator = Vector3Argument.findIn(lv, cposLocator.offset);
final Vector3Argument diffLocator = Vector3Argument.findIn(lv, cposLocator.offset);
if (diffLocator.fromBlock)
{
sminx = Mth.floor(abs(diffLocator.vec.x - cx));
@@ -256,7 +271,7 @@ public class BlockIterators {
}
if (lv.size() > diffLocator.offset)
{
Vector3Argument posDiff = Vector3Argument.findIn(lv, diffLocator.offset);
final Vector3Argument posDiff = Vector3Argument.findIn(lv, diffLocator.offset);
if (posDiff.fromBlock)
{
smaxx = Mth.floor(abs(posDiff.vec.x - cx));
@@ -289,19 +304,21 @@ public class BlockIterators {
return new LazyListValue()
{
final int minx = cx-sminx;
final int miny = cy-sminy;
final int minz = cz-sminz;
final int maxx = cx+smaxx;
final int maxy = cy+smaxy;
final int maxz = cz+smaxz;
final int minx = cx - sminx;
final int miny = cy - sminy;
final int minz = cz - sminz;
final int maxx = cx + smaxx;
final int maxy = cy + smaxy;
final int maxz = cz + smaxz;
int x;
int y;
int z;
{
reset();
}
@Override
public boolean hasNext()
{
@@ -311,7 +328,7 @@ public class BlockIterators {
@Override
public Value next()
{
Value r = BlockValue.fromCoords(cc, x,y,z);
final Value r = BlockValue.fromCoords(cc, x, y, z);
//possibly reroll context
x++;
if (x > maxx)
@@ -347,56 +364,57 @@ public class BlockIterators {
@Override
public String getString()
{
return String.format(Locale.ROOT, "rect[(%d,%d,%d),..,(%d,%d,%d)]",minx, miny, minz, maxx, maxy, maxz);
return String.format(Locale.ROOT, "rect[(%d,%d,%d),..,(%d,%d,%d)]", minx, miny, minz, maxx, maxy, maxz);
}
};
});
expression.addContextFunction("diamond", -1, (c, t, lv)->
expression.addContextFunction("diamond", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
final CarpetContext cc = (CarpetContext) c;
BlockArgument cposLocator=BlockArgument.findIn((CarpetContext)c,lv,0);
BlockPos cpos = cposLocator.block.getPos();
final BlockArgument cposLocator = BlockArgument.findIn((CarpetContext) c, lv, 0);
final BlockPos cpos = cposLocator.block.getPos();
int cx;
int cy;
int cz;
int width;
int height;
final int cx;
final int cy;
final int cz;
final int width;
final int height;
try
{
cx = cpos.getX();
cy = cpos.getY();
cz = cpos.getZ();
if (lv.size()==cposLocator.offset)
if (lv.size() == cposLocator.offset)
{
Value retval = ListValue.of(
BlockValue.fromCoords(cc, cx, cy-1, cz),
return ListValue.of(
BlockValue.fromCoords(cc, cx, cy - 1, cz),
BlockValue.fromCoords(cc, cx, cy, cz),
BlockValue.fromCoords(cc, cx-1, cy, cz),
BlockValue.fromCoords(cc, cx, cy, cz-1),
BlockValue.fromCoords(cc, cx+1, cy, cz),
BlockValue.fromCoords(cc, cx, cy, cz+1),
BlockValue.fromCoords(cc, cx, cy+1, cz)
BlockValue.fromCoords(cc, cx - 1, cy, cz),
BlockValue.fromCoords(cc, cx, cy, cz - 1),
BlockValue.fromCoords(cc, cx + 1, cy, cz),
BlockValue.fromCoords(cc, cx, cy, cz + 1),
BlockValue.fromCoords(cc, cx, cy + 1, cz)
);
return retval;
}
else if (lv.size()==1+cposLocator.offset)
else if (lv.size() == 1 + cposLocator.offset)
{
width = (int) ((NumericValue) lv.get(cposLocator.offset)).getLong();
height = 0;
}
else if(lv.size()==2+cposLocator.offset)
else if (lv.size() == 2 + cposLocator.offset)
{
width = (int) ((NumericValue) lv.get(cposLocator.offset)).getLong();
height = (int) ((NumericValue) lv.get(cposLocator.offset+1)).getLong();
} else{
height = (int) ((NumericValue) lv.get(cposLocator.offset + 1)).getLong();
}
else
{
throw new InternalExpressionException("Incorrect number of arguments for 'diamond'");
}
}
catch (ClassCastException exc)
catch (final ClassCastException ignored)
{
throw new InternalExpressionException("Attempted to pass a non-number to 'diamond'");
}
@@ -406,9 +424,11 @@ public class BlockIterators {
{
int curradius;
int curpos;
{
reset();
}
@Override
public boolean hasNext()
{
@@ -425,9 +445,9 @@ public class BlockIterators {
}
// x = 3-|i-6|
// z = |( (i-3)%12-6|-3
Value block = BlockValue.fromCoords(cc, cx+(curradius-abs(curpos-2*curradius)), cy, cz-curradius+abs( abs(curpos-curradius)%(4*curradius) -2*curradius ));
final Value block = BlockValue.fromCoords(cc, cx + (curradius - abs(curpos - 2 * curradius)), cy, cz - curradius + abs(abs(curpos - curradius) % (4 * curradius) - 2 * curradius));
curpos++;
if (curpos>=curradius*4)
if (curpos >= curradius * 4)
{
curradius++;
curpos = 0;
@@ -446,7 +466,7 @@ public class BlockIterators {
@Override
public String getString()
{
return String.format(Locale.ROOT, "diamond[(%d,%d,%d),%d,0]",cx, cy, cz, width);
return String.format(Locale.ROOT, "diamond[(%d,%d,%d),%d,0]", cx, cy, cz, width);
}
};
}
@@ -457,9 +477,11 @@ public class BlockIterators {
int curradius;
int curpos;
int curheight;
{
reset();
}
@Override
public boolean hasNext()
{
@@ -471,27 +493,26 @@ public class BlockIterators {
{
if (curheight == -height || curheight == height)
{
return BlockValue.fromCoords(cc, cx, cy+curheight++, cz);
return BlockValue.fromCoords(cc, cx, cy + curheight++, cz);
}
if (curradius == 0)
{
curradius++;
return BlockValue.fromCoords(cc, cx, cy+curheight, cz);
return BlockValue.fromCoords(cc, cx, cy + curheight, cz);
}
// x = 3-|i-6|
// z = |( (i-3)%12-6|-3
Value block = BlockValue.fromCoords(cc, cx+(curradius-abs(curpos-2*curradius)), cy+curheight, cz-curradius+abs( abs(curpos-curradius)%(4*curradius) -2*curradius ));
final Value block = BlockValue.fromCoords(cc, cx + (curradius - abs(curpos - 2 * curradius)), cy + curheight, cz - curradius + abs(abs(curpos - curradius) % (4 * curradius) - 2 * curradius));
curpos++;
if (curpos>=curradius*4)
if (curpos >= curradius * 4)
{
curradius++;
curpos = 0;
if (curradius>width -abs(width*curheight/height))
if (curradius > width - abs(width * curheight / height))
{
curheight++;
curradius = 0;
curpos = 0;
}
}
return block;
@@ -508,7 +529,7 @@ public class BlockIterators {
@Override
public String getString()
{
return String.format(Locale.ROOT, "diamond[(%d,%d,%d),%d,%d]",cx, cy, cz, width, height);
return String.format(Locale.ROOT, "diamond[(%d,%d,%d),%d,%d]", cx, cy, cz, width, height);
}
};
}
+157 -117
View File
@@ -15,6 +15,7 @@ import carpet.script.value.NumericValue;
import carpet.script.value.Value;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -23,6 +24,7 @@ import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import java.util.function.Predicate;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
@@ -38,159 +40,183 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
public class Entities {
private static ListValue getPlayersFromWorldMatching(Context c, Predicate<ServerPlayer> condition) {
List<Value> ret = new ArrayList<>();
for (ServerPlayer player: ((CarpetContext) c).level().players()) {
if (condition.test(player)) {
public class Entities
{
private static ListValue getPlayersFromWorldMatching(final Context c, final Predicate<ServerPlayer> condition)
{
final List<Value> ret = new ArrayList<>();
for (final ServerPlayer player : ((CarpetContext) c).level().players())
{
if (condition.test(player))
{
ret.add(new EntityValue(player));
}
}
return ListValue.wrap(ret);
}
public static void apply(Expression expression)
public static void apply(final Expression expression)
{
expression.addContextFunction("player", -1, (c, t, lv) ->
{
if (lv.size() == 0)
{
CarpetContext cc = (CarpetContext)c;
final CarpetContext cc = (CarpetContext) c;
if (cc.host.user != null)
{
ServerPlayer player = cc.server().getPlayerList().getPlayerByName(cc.host.user);
final ServerPlayer player = cc.server().getPlayerList().getPlayerByName(cc.host.user);
return EntityValue.of(player);
}
Entity callingEntity = cc.source().getEntity();
if (callingEntity instanceof Player) return EntityValue.of(callingEntity);
Vec3 pos = ((CarpetContext)c).source().getPosition();
Player closestPlayer = ((CarpetContext)c).level().getNearestPlayer(pos.x, pos.y, pos.z, -1.0, EntitySelector.ENTITY_STILL_ALIVE);
final Entity callingEntity = cc.source().getEntity();
if (callingEntity instanceof Player)
{
return EntityValue.of(callingEntity);
}
final Vec3 pos = ((CarpetContext) c).source().getPosition();
final Player closestPlayer = ((CarpetContext) c).level().getNearestPlayer(pos.x, pos.y, pos.z, -1.0, EntitySelector.ENTITY_STILL_ALIVE);
return EntityValue.of(closestPlayer);
}
String playerName = lv.get(0).getString();
return switch (playerName) {
case "all" -> {
List<Value> ret = new ArrayList<>();
for (ServerPlayer player: ((CarpetContext)c).server().getPlayerList().getPlayers())
ret.add(new EntityValue(player));
yield ListValue.wrap(ret);
}
case "*" -> getPlayersFromWorldMatching(c, p -> true);
case "survival" -> getPlayersFromWorldMatching(c, p -> p.gameMode.isSurvival()); // todo assert correct
case "creative" -> getPlayersFromWorldMatching(c, ServerPlayer::isCreative);
case "spectating" -> getPlayersFromWorldMatching(c, ServerPlayer::isSpectator);
case "!spectating" -> getPlayersFromWorldMatching(c, p -> !p.isSpectator());
default -> {
ServerPlayer player = ((CarpetContext) c).server().getPlayerList().getPlayerByName(playerName);
if (player != null) {
yield new EntityValue(player);
}
yield Value.NULL;
}
};
final String playerName = lv.get(0).getString();
return switch (playerName)
{
case "all" -> {
final List<Value> ret = new ArrayList<>();
for (final ServerPlayer player : ((CarpetContext) c).server().getPlayerList().getPlayers())
{
ret.add(new EntityValue(player));
}
yield ListValue.wrap(ret);
}
case "*" -> getPlayersFromWorldMatching(c, p -> true);
case "survival" -> getPlayersFromWorldMatching(c, p -> p.gameMode.isSurvival()); // todo assert correct
case "creative" -> getPlayersFromWorldMatching(c, ServerPlayer::isCreative);
case "spectating" -> getPlayersFromWorldMatching(c, ServerPlayer::isSpectator);
case "!spectating" -> getPlayersFromWorldMatching(c, p -> !p.isSpectator());
default -> {
final ServerPlayer player = ((CarpetContext) c).server().getPlayerList().getPlayerByName(playerName);
yield player != null ? new EntityValue(player) : Value.NULL;
}
};
});
expression.addContextFunction("spawn", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
final CarpetContext cc = (CarpetContext) c;
if (lv.size() < 2)
{
throw new InternalExpressionException("'spawn' function takes mob name, and position to spawn");
String entityString = lv.get(0).getString();
ResourceLocation entityId;
}
final String entityString = lv.get(0).getString();
final ResourceLocation entityId;
try
{
entityId = ResourceLocation.read(new StringReader(entityString));
EntityType<? extends Entity> type = cc.registry(Registries.ENTITY_TYPE).getOptional(entityId).orElse(null);
final EntityType<? extends Entity> type = cc.registry(Registries.ENTITY_TYPE).getOptional(entityId).orElse(null);
if (type == null || !type.canSummon())
{
return Value.NULL;
}
}
catch (CommandSyntaxException exception)
catch (final CommandSyntaxException ignored)
{
return Value.NULL;
return Value.NULL;
}
Vector3Argument position = Vector3Argument.findIn(lv, 1);
final Vector3Argument position = Vector3Argument.findIn(lv, 1);
if (position.fromBlock)
{
position.vec = position.vec.subtract(0, 0.5, 0);
}
CompoundTag tag = new CompoundTag();
boolean hasTag = false;
if (lv.size() > position.offset)
{
Value nbt = lv.get(position.offset);
NBTSerializableValue v = (nbt instanceof NBTSerializableValue) ? (NBTSerializableValue) nbt
final Value nbt = lv.get(position.offset);
final NBTSerializableValue v = (nbt instanceof final NBTSerializableValue nbtsv)
? nbtsv
: NBTSerializableValue.parseString(nbt.getString(), true);
hasTag = true;
tag = v.getCompoundTag();
}
tag.putString("id", entityId.toString());
Vec3 vec3d = position.vec;
final Vec3 vec3d = position.vec;
ServerLevel serverWorld = cc.level();
Entity entity_1 = EntityType.loadEntityRecursive(tag, serverWorld, (entity_1x) -> {
entity_1x.moveTo(vec3d.x, vec3d.y, vec3d.z, entity_1x.getYRot(), entity_1x.getXRot());
return !serverWorld.addWithUUID(entity_1x) ? null : entity_1x;
final ServerLevel serverWorld = cc.level();
final Entity entity = EntityType.loadEntityRecursive(tag, serverWorld, e -> {
e.moveTo(vec3d.x, vec3d.y, vec3d.z, e.getYRot(), e.getXRot());
return !serverWorld.addWithUUID(e) ? null : e;
});
if (entity_1 == null) {
if (entity == null)
{
return Value.NULL;
} else {
if (!hasTag && entity_1 instanceof Mob) {
((Mob)entity_1).finalizeSpawn(serverWorld, serverWorld.getCurrentDifficultyAt(entity_1.blockPosition()), MobSpawnType.COMMAND, null, null);
}
return new EntityValue(entity_1);
}
if (!hasTag && entity instanceof final Mob mob)
{
mob.finalizeSpawn(serverWorld, serverWorld.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.COMMAND, null, null);
}
return new EntityValue(entity);
});
expression.addContextFunction("entity_id", 1, (c, t, lv) ->
{
Value who = lv.get(0);
if (who instanceof NumericValue)
return EntityValue.of(((CarpetContext)c).level().getEntity((int)((NumericValue) who).getLong()));
return EntityValue.of(((CarpetContext)c).level().getEntity(UUID.fromString(who.getString())));
final Value who = lv.get(0);
if (who instanceof final NumericValue numericValue)
{
return EntityValue.of(((CarpetContext) c).level().getEntity((int) numericValue.getLong()));
}
return EntityValue.of(((CarpetContext) c).level().getEntity(UUID.fromString(who.getString())));
});
expression.addContextFunction("entity_list", 1, (c, t, lv) ->
{
String who = lv.get(0).getString();
CommandSourceStack source = ((CarpetContext)c).source();
EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, source.getServer());
List<? extends Entity> entityList = source.getLevel().getEntities(eDesc.directType, eDesc.filteringPredicate);
final String who = lv.get(0).getString();
final CommandSourceStack source = ((CarpetContext) c).source();
final EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, source.getServer());
final List<? extends Entity> entityList = source.getLevel().getEntities(eDesc.directType, eDesc.filteringPredicate);
return ListValue.wrap(entityList.stream().map(EntityValue::new));
});
expression.addContextFunction("entity_area", -1, (c, t, lv) ->
{
if (lv.size()<3) throw new InternalExpressionException("'entity_area' requires entity type, center and range arguments");
String who = lv.get(0).getString();
CarpetContext cc = (CarpetContext)c;
Vector3Argument centerLocator = Vector3Argument.findIn(lv, 1, false, true);
if (lv.size() < 3)
{
throw new InternalExpressionException("'entity_area' requires entity type, center and range arguments");
}
final String who = lv.get(0).getString();
final CarpetContext cc = (CarpetContext) c;
final Vector3Argument centerLocator = Vector3Argument.findIn(lv, 1, false, true);
AABB centerBox;
final AABB centerBox;
if (centerLocator.entity != null)
{
centerBox = centerLocator.entity.getBoundingBox();
}
else
{
Vec3 center = centerLocator.vec;
if (centerLocator.fromBlock) center.add(0.5, 0.5, 0.5);
final Vec3 center = centerLocator.vec;
if (centerLocator.fromBlock)
{
center.add(0.5, 0.5, 0.5);
}
centerBox = new AABB(center, center);
}
Vector3Argument rangeLocator = Vector3Argument.findIn(lv, centerLocator.offset);
final Vector3Argument rangeLocator = Vector3Argument.findIn(lv, centerLocator.offset);
if (rangeLocator.fromBlock)
{
throw new InternalExpressionException("Range of 'entity_area' cannot come from a block argument");
Vec3 range = rangeLocator.vec;
AABB area = centerBox.inflate(range.x, range.y, range.z);
EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, cc.server());
List<? extends Entity> entityList = cc.level().getEntities(eDesc.directType, area,eDesc.filteringPredicate);
}
final Vec3 range = rangeLocator.vec;
final AABB area = centerBox.inflate(range.x, range.y, range.z);
final EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, cc.server());
final List<? extends Entity> entityList = cc.level().getEntities(eDesc.directType, area, eDesc.filteringPredicate);
return ListValue.wrap(entityList.stream().map(EntityValue::new));
});
expression.addContextFunction("entity_selector", -1, (c, t, lv) ->
{
String selector = lv.get(0).getString();
List<Value> retlist = new ArrayList<>();
for (Entity e: EntityValue.getEntitiesFromSelector(((CarpetContext)c).source(), selector))
final String selector = lv.get(0).getString();
final List<Value> retlist = new ArrayList<>();
for (final Entity e : EntityValue.getEntitiesFromSelector(((CarpetContext) c).source(), selector))
{
retlist.add(new EntityValue(e));
}
@@ -199,64 +225,74 @@ public class Entities {
expression.addContextFunction("query", -1, (c, t, lv) ->
{
if (lv.size()<2)
if (lv.size() < 2)
{
throw new InternalExpressionException("'query' takes entity as a first argument, and queried feature as a second");
}
Value v = lv.get(0);
if (!(v instanceof EntityValue))
final Value v = lv.get(0);
if (!(v instanceof final EntityValue ev))
{
throw new InternalExpressionException("First argument to query should be an entity");
String what = lv.get(1).getString().toLowerCase(Locale.ROOT);
}
final String what = lv.get(1).getString().toLowerCase(Locale.ROOT);
if (what.equals("tags"))
{
c.host.issueDeprecation("'tags' for entity querying");
Value retval;
if (lv.size()==2)
retval = ((EntityValue) v).get(what, null);
else if (lv.size()==3)
retval = ((EntityValue) v).get(what, lv.get(2));
else
retval = ((EntityValue) v).get(what, ListValue.wrap(lv.subList(2, lv.size())));
return retval;
}
return switch (lv.size())
{
case 2 -> ev.get(what, null);
case 3 -> ev.get(what, lv.get(2));
default -> ev.get(what, ListValue.wrap(lv.subList(2, lv.size())));
};
});
// or update
expression.addContextFunction("modify", -1, (c, t, lv) ->
{
if (lv.size()<2)
if (lv.size() < 2)
{
throw new InternalExpressionException("'modify' takes entity as a first argument, and queried feature as a second");
}
Value v = lv.get(0);
if (!(v instanceof EntityValue))
final Value v = lv.get(0);
if (!(v instanceof final EntityValue ev))
{
throw new InternalExpressionException("First argument to modify should be an entity");
String what = lv.get(1).getString();
if (lv.size()==2)
((EntityValue) v).set(what, null);
else if (lv.size()==3)
((EntityValue) v).set(what, lv.get(2));
else
((EntityValue) v).set(what, ListValue.wrap(lv.subList(2, lv.size())));
}
final String what = lv.get(1).getString();
switch (lv.size())
{
case 2 -> ev.set(what, null);
case 3 -> ev.set(what, lv.get(2));
default -> ev.set(what, ListValue.wrap(lv.subList(2, lv.size())));
}
return v;
});
expression.addContextFunction("entity_types", -1, (c, t, lv) ->
{
if (lv.size() > 1) throw new InternalExpressionException("'entity_types' requires one or no arguments");
String desc = (lv.size() == 1)?lv.get(0).getString():"*";
return EntityValue.getEntityDescriptor(desc, ((CarpetContext) c).server()).listValue(((CarpetContext)c).registryAccess());
if (lv.size() > 1)
{
throw new InternalExpressionException("'entity_types' requires one or no arguments");
}
final String desc = (lv.size() == 1) ? lv.get(0).getString() : "*";
return EntityValue.getEntityDescriptor(desc, ((CarpetContext) c).server()).listValue(((CarpetContext) c).registryAccess());
});
expression.addContextFunction("entity_load_handler", -1, (c, t, lv) ->
{
if (lv.size() < 2) throw new InternalExpressionException("'entity_load_handler' required the entity type, and a function to call");
Value entityValue = lv.get(0);
List<String> descriptors = (entityValue instanceof ListValue)
? ((ListValue) entityValue).getItems().stream().map(Value::getString).toList()
if (lv.size() < 2)
{
throw new InternalExpressionException("'entity_load_handler' required the entity type, and a function to call");
}
final Value entityValue = lv.get(0);
final List<String> descriptors = (entityValue instanceof final ListValue list)
? list.getItems().stream().map(Value::getString).toList()
: Collections.singletonList(entityValue.getString());
Set<EntityType<? extends Entity>> types = new HashSet<>();
final Set<EntityType<? extends Entity>> types = new HashSet<>();
descriptors.forEach(s -> types.addAll(EntityValue.getEntityDescriptor(s, ((CarpetContext) c).server()).types));
FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 1, true, false);
CarpetEventServer events = ((CarpetScriptHost)c.host).scriptServer().events;
final FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 1, true, false);
final CarpetEventServer events = ((CarpetScriptHost) c.host).scriptServer().events;
if (funArg.function == null)
{
types.forEach(et -> events.removeBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), (CarpetScriptHost) c.host));
@@ -265,8 +301,8 @@ public class Entities {
else
{
///compat
int argno = funArg.function.getArguments().size() - funArg.args.size();
if (argno == 1)
final int numberOfArguments = funArg.function.getArguments().size() - funArg.args.size();
if (numberOfArguments == 1)
{
c.host.issueDeprecation("entity_load_handler() with single argument callback");
types.forEach(et -> events.addBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), c.host, funArg.function, funArg.args));
@@ -282,16 +318,20 @@ public class Entities {
// or update
expression.addContextFunction("entity_event", -1, (c, t, lv) ->
{
if (lv.size()<3)
if (lv.size() < 3)
{
throw new InternalExpressionException("'entity_event' requires at least 3 arguments, entity, event to be handled, and function name, with optional arguments");
Value v = lv.get(0);
if (!(v instanceof EntityValue))
}
final Value v = lv.get(0);
if (!(v instanceof final EntityValue ev))
{
throw new InternalExpressionException("First argument to entity_event should be an entity");
String what = lv.get(1).getString();
}
final String what = lv.get(1).getString();
FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, false);
final FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, false);
((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, funArg.args);
ev.setEvent((CarpetContext) c, what, funArg.function, funArg.args);
return Value.NULL;
});
+251 -199
View File
@@ -21,11 +21,13 @@ import carpet.script.value.StringValue;
import carpet.script.value.Value;
import carpet.script.value.ValueConversions;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import net.minecraft.commands.arguments.item.ItemInput;
import net.minecraft.core.HolderSet;
import net.minecraft.core.Registry;
@@ -51,129 +53,110 @@ import net.minecraft.world.item.crafting.ShapelessRecipe;
import net.minecraft.world.item.crafting.SingleItemRecipe;
import net.minecraft.world.phys.Vec3;
public class Inventories {
public static void apply(Expression expression)
public class Inventories
{
public static void apply(final Expression expression)
{
expression.addContextFunction("stack_limit", 1, (c, t, lv) ->
new NumericValue(NBTSerializableValue.parseItem(lv.get(0).getString(), ((CarpetContext) c).registryAccess() ).getItem().getMaxStackSize()));
new NumericValue(NBTSerializableValue.parseItem(lv.get(0).getString(), ((CarpetContext) c).registryAccess()).getItem().getMaxStackSize()));
expression.addContextFunction("item_category", -1, (c, t, lv) -> {
CarpetContext cc = (CarpetContext)c;
cc.host.issueDeprecation("item_category in 1.19.3+");
c.host.issueDeprecation("item_category in 1.19.3+");
return Value.NULL;
});
expression.addContextFunction("item_list", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
Registry<Item> items = cc.registry(Registries.ITEM);
final CarpetContext cc = (CarpetContext) c;
final Registry<Item> items = cc.registry(Registries.ITEM);
if (lv.size() == 0)
{
return ListValue.wrap(items.keySet().stream().map(ValueConversions::of));
String tag = lv.get(0).getString();
Optional<HolderSet.Named<Item>> itemTag = items.getTag(TagKey.create(Registries.ITEM, InputValidator.identifierOf(tag)));
if (itemTag.isEmpty()) return Value.NULL;
return ListValue.wrap(itemTag.get().stream().map(b -> ValueConversions.of(items.getKey(b.value()))));
/*
TagContainer tagManager = cc.s.getServer(). getTags();
String tag = lv.get(0).getString();
net.minecraft.tags.Tag<Item> itemTag = tagManager.getOrEmpty(Registry.ITEM_REGISTRY).getTag(InputValidator.identifierOf(tag));
if (itemTag == null) return Value.NULL;
return ListValue.wrap(itemTag.getValues().stream().map(b -> ValueConversions.of(Registry.ITEM.getKey(b))));
*/
}
final String tag = lv.get(0).getString();
final Optional<HolderSet.Named<Item>> itemTag = items.getTag(TagKey.create(Registries.ITEM, InputValidator.identifierOf(tag)));
return itemTag.isEmpty() ? Value.NULL : ListValue.wrap(itemTag.get().stream().map(b -> ValueConversions.of(items.getKey(b.value()))));
});
expression.addContextFunction("item_tags", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
final CarpetContext cc = (CarpetContext) c;
Registry<Item> blocks = cc.registry(Registries.ITEM);
final Registry<Item> blocks = cc.registry(Registries.ITEM);
if (lv.size() == 0)
{
return ListValue.wrap(blocks.getTagNames().map(ValueConversions::of));
Item item = NBTSerializableValue.parseItem(lv.get(0).getString(), cc.registryAccess()).getItem();
}
final Item item = NBTSerializableValue.parseItem(lv.get(0).getString(), cc.registryAccess()).getItem();
if (lv.size() == 1)
{
return ListValue.wrap( blocks.getTags().filter(e -> e.getSecond().stream().anyMatch(h -> (h.value() == item))).map(e -> ValueConversions.of(e.getFirst())));
return ListValue.wrap(blocks.getTags().filter(e -> e.getSecond().stream().anyMatch(h -> (h.value() == item))).map(e -> ValueConversions.of(e.getFirst())));
}
String tag = lv.get(1).getString();
Optional<HolderSet.Named<Item>> tagSet = blocks.getTag(TagKey.create(Registries.ITEM, InputValidator.identifierOf(tag)));
if (tagSet.isEmpty()) return Value.NULL;
//return BooleanValue.of(tagSet.get().contains(item.builtInRegistryHolder()));
return BooleanValue.of(tagSet.get().stream().anyMatch(h -> h.value() == item));
/*
TagContainer tagManager = cc.s.getServer().getTags();
if (lv.size() == 0)
return ListValue.wrap(tagManager.getOrEmpty(Registry.ITEM_REGISTRY).getAvailableTags().stream().map(ValueConversions::of));
Item item = NBTSerializableValue.parseItem(lv.get(0).getString()).getItem();
if (lv.size() == 1)
return ListValue.wrap(tagManager.getOrEmpty(Registry.ITEM_REGISTRY).getAllTags().entrySet().stream().filter(e -> e.getValue().contains(item)).map(e -> ValueConversions.of(e.getKey())));
String tag = lv.get(1).getString();
net.minecraft.tags.Tag<Item> itemTag = tagManager.getOrEmpty(Registry.ITEM_REGISTRY).getTag(InputValidator.identifierOf(tag));
if (itemTag == null) return Value.NULL;
return BooleanValue.of(itemTag.contains(item));
*/
final String tag = lv.get(1).getString();
final Optional<HolderSet.Named<Item>> tagSet = blocks.getTag(TagKey.create(Registries.ITEM, InputValidator.identifierOf(tag)));
return tagSet.isEmpty() ? Value.NULL : BooleanValue.of(tagSet.get().stream().anyMatch(h -> h.value() == item));
});
expression.addContextFunction("recipe_data", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
if (lv.size() < 1) throw new InternalExpressionException("'recipe_data' requires at least one argument");
String recipeName = lv.get(0).getString();
final CarpetContext cc = (CarpetContext) c;
if (lv.size() < 1)
{
throw new InternalExpressionException("'recipe_data' requires at least one argument");
}
final String recipeName = lv.get(0).getString();
RecipeType<?> type = RecipeType.CRAFTING;
if (lv.size() > 1)
{
String recipeType = lv.get(1).getString();
final String recipeType = lv.get(1).getString();
type = cc.registry(Registries.RECIPE_TYPE).get(InputValidator.identifierOf(recipeType));
}
List<Recipe<?>> recipes;
recipes = ((RecipeManagerInterface) cc.server().getRecipeManager()).getAllMatching(type, InputValidator.identifierOf(recipeName), cc.registryAccess());
final List<Recipe<?>> recipes = ((RecipeManagerInterface) cc.server().getRecipeManager()).getAllMatching(type, InputValidator.identifierOf(recipeName), cc.registryAccess());
if (recipes.isEmpty())
return Value.NULL;
List<Value> recipesOutput = new ArrayList<>();
RegistryAccess regs = cc.registryAccess();
for (Recipe<?> recipe: recipes)
{
ItemStack result = recipe.getResultItem(regs);
List<Value> ingredientValue = new ArrayList<>();
recipe.getIngredients().forEach(
ingredient ->
{
// I am flattening ingredient lists per slot.
// consider recipe_data('wooden_sword','crafting') and ('iron_nugget', 'blasting') and notice difference
// in depths of lists.
List<Collection<ItemStack>> stacks = ((IngredientInterface) (Object) ingredient).getRecipeStacks();
if (stacks.isEmpty())
{
ingredientValue.add(Value.NULL);
}
else
{
List<Value> alternatives = new ArrayList<>();
stacks.forEach(col -> col.stream().map(is -> ValueConversions.of(is, regs)).forEach(alternatives::add));
ingredientValue.add(ListValue.wrap(alternatives));
}
}
);
Value recipeSpec;
if (recipe instanceof ShapedRecipe)
return Value.NULL;
}
final List<Value> recipesOutput = new ArrayList<>();
final RegistryAccess regs = cc.registryAccess();
for (final Recipe<?> recipe : recipes)
{
final ItemStack result = recipe.getResultItem(regs);
final List<Value> ingredientValue = new ArrayList<>();
recipe.getIngredients().forEach( ingredient -> {
// I am flattening ingredient lists per slot.
// consider recipe_data('wooden_sword','crafting') and ('iron_nugget', 'blasting') and notice difference
// in depths of lists.
final List<Collection<ItemStack>> stacks = ((IngredientInterface) (Object) ingredient).getRecipeStacks();
if (stacks.isEmpty())
{
ingredientValue.add(Value.NULL);
}
else
{
final List<Value> alternatives = new ArrayList<>();
stacks.forEach(col -> col.stream().map(is -> ValueConversions.of(is, regs)).forEach(alternatives::add));
ingredientValue.add(ListValue.wrap(alternatives));
}
});
final Value recipeSpec;
if (recipe instanceof final ShapedRecipe shapedRecipe)
{
recipeSpec = ListValue.of(
new StringValue("shaped"),
new NumericValue(((ShapedRecipe) recipe).getWidth()),
new NumericValue(((ShapedRecipe) recipe).getHeight())
new NumericValue(shapedRecipe.getWidth()),
new NumericValue(shapedRecipe.getHeight())
);
}
else if (recipe instanceof ShapelessRecipe)
{
recipeSpec = ListValue.of(new StringValue("shapeless"));
}
else if (recipe instanceof AbstractCookingRecipe)
else if (recipe instanceof final AbstractCookingRecipe abstractCookingRecipe)
{
recipeSpec = ListValue.of(
new StringValue("smelting"),
new NumericValue(((AbstractCookingRecipe) recipe).getCookingTime()),
new NumericValue(((AbstractCookingRecipe) recipe).getExperience())
new NumericValue(abstractCookingRecipe.getCookingTime()),
new NumericValue(abstractCookingRecipe.getExperience())
);
}
else if (recipe instanceof SingleItemRecipe)
@@ -196,100 +179,117 @@ public class Inventories {
expression.addContextFunction("crafting_remaining_item", 1, (c, t, v) ->
{
String itemStr = v.get(0).getString();
Item item;
ResourceLocation id = InputValidator.identifierOf(itemStr);
Registry<Item> registry = ((CarpetContext)c).registry(Registries.ITEM);
item = registry.getOptional(id).orElseThrow(() -> new ThrowStatement(itemStr, Throwables.UNKNOWN_ITEM));
if (!item.hasCraftingRemainingItem()) return Value.NULL;
return new StringValue(NBTSerializableValue.nameFromRegistryId(registry.getKey(item.getCraftingRemainingItem())));
final String itemStr = v.get(0).getString();
final ResourceLocation id = InputValidator.identifierOf(itemStr);
final Registry<Item> registry = ((CarpetContext) c).registry(Registries.ITEM);
final Item item = registry.getOptional(id).orElseThrow(() -> new ThrowStatement(itemStr, Throwables.UNKNOWN_ITEM));
return !item.hasCraftingRemainingItem()
? Value.NULL
: new StringValue(NBTSerializableValue.nameFromRegistryId(registry.getKey(item.getCraftingRemainingItem())));
});
expression.addContextFunction("inventory_size", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext) c;
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
if (inventoryLocator == null) return Value.NULL;
return new NumericValue(inventoryLocator.inventory().getContainerSize());
final CarpetContext cc = (CarpetContext) c;
final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
return inventoryLocator == null ? Value.NULL : new NumericValue(inventoryLocator.inventory().getContainerSize());
});
expression.addContextFunction("inventory_has_items", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext) c;
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
if (inventoryLocator == null) return Value.NULL;
return BooleanValue.of(!inventoryLocator.inventory().isEmpty());
final CarpetContext cc = (CarpetContext) c;
final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
return inventoryLocator == null ? Value.NULL : BooleanValue.of(!inventoryLocator.inventory().isEmpty());
});
//inventory_get(<b, e>, <n>) -> item_triple
expression.addContextFunction("inventory_get", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext) c;
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
if (inventoryLocator == null) return Value.NULL;
RegistryAccess regs = cc.registryAccess();
final CarpetContext cc = (CarpetContext) c;
final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
if (inventoryLocator == null)
{
return Value.NULL;
}
final RegistryAccess regs = cc.registryAccess();
if (lv.size() == inventoryLocator.offset())
{
List<Value> fullInventory = new ArrayList<>();
final List<Value> fullInventory = new ArrayList<>();
for (int i = 0, maxi = inventoryLocator.inventory().getContainerSize(); i < maxi; i++)
{
fullInventory.add(ValueConversions.of(inventoryLocator.inventory().getItem(i), regs));
}
return ListValue.wrap(fullInventory);
}
int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset())).getLong();
int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset())).getLong();
slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory());
if (slot == inventoryLocator.inventory().getContainerSize()) return Value.NULL;
return ValueConversions.of(inventoryLocator.inventory().getItem(slot), regs);
return slot == inventoryLocator.inventory().getContainerSize()
? Value.NULL
: ValueConversions.of(inventoryLocator.inventory().getItem(slot), regs);
});
//inventory_set(<b,e>, <n>, <count>, <item>, <nbt>)
expression.addContextFunction("inventory_set", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext) c;
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
if (inventoryLocator == null) return Value.NULL;
if (lv.size() < inventoryLocator.offset()+2)
final CarpetContext cc = (CarpetContext) c;
final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
if (inventoryLocator == null)
{
return Value.NULL;
}
if (lv.size() < inventoryLocator.offset() + 2)
{
throw new InternalExpressionException("'inventory_set' requires at least slot number and new stack size, and optional new item");
int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset()+0)).getLong();
}
int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset() + 0)).getLong();
slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory());
if (slot == inventoryLocator.inventory().getContainerSize()) return Value.NULL;
int count = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset()+1)).getLong();
RegistryAccess regs = cc.registryAccess();
if (slot == inventoryLocator.inventory().getContainerSize())
{
return Value.NULL;
}
final int count = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset() + 1)).getLong();
final RegistryAccess regs = cc.registryAccess();
if (count == 0)
{
// clear slot
ItemStack removedStack = inventoryLocator.inventory().removeItemNoUpdate(slot);
final ItemStack removedStack = inventoryLocator.inventory().removeItemNoUpdate(slot);
syncPlayerInventory(inventoryLocator, slot);
//Value res = ListValue.fromItemStack(removedStack); // that tuple will be read only but cheaper if noone cares
return ValueConversions.of(removedStack, regs);
}
if (lv.size() < inventoryLocator.offset()+3)
if (lv.size() < inventoryLocator.offset() + 3)
{
ItemStack previousStack = inventoryLocator.inventory().getItem(slot);
ItemStack newStack = previousStack.copy();
final ItemStack previousStack = inventoryLocator.inventory().getItem(slot);
final ItemStack newStack = previousStack.copy();
newStack.setCount(count);
inventoryLocator.inventory().setItem(slot, newStack);
syncPlayerInventory(inventoryLocator, slot);
return ValueConversions.of(previousStack, regs);
}
CompoundTag nbt = null; // skipping one argument
if (lv.size() > inventoryLocator.offset()+3)
if (lv.size() > inventoryLocator.offset() + 3)
{
Value nbtValue = lv.get(inventoryLocator.offset()+3);
if (nbtValue instanceof NBTSerializableValue)
nbt = ((NBTSerializableValue)nbtValue).getCompoundTag();
final Value nbtValue = lv.get(inventoryLocator.offset() + 3);
if (nbtValue instanceof final NBTSerializableValue nbtsv)
{
nbt = nbtsv.getCompoundTag();
}
else if (nbtValue.isNull())
{
nbt = null;
}
else
{
nbt = new NBTSerializableValue(nbtValue.getString()).getCompoundTag();
}
}
ItemInput newitem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset()+2).getString(), nbt, cc.registryAccess());
ItemStack previousStack = inventoryLocator.inventory().getItem(slot);
final ItemInput newitem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset() + 2).getString(), nbt, cc.registryAccess());
final ItemStack previousStack = inventoryLocator.inventory().getItem(slot);
try
{
inventoryLocator.inventory().setItem(slot, newitem.createItemStack(count, false));
syncPlayerInventory(inventoryLocator, slot);
}
catch (CommandSyntaxException e)
catch (final CommandSyntaxException e)
{
throw new InternalExpressionException(e.getMessage());
}
@@ -299,27 +299,34 @@ public class Inventories {
//inventory_find(<b, e>, <item> or null (first empty slot), <start_from=0> ) -> <N> or null
expression.addContextFunction("inventory_find", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext) c;
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
if (inventoryLocator == null) return Value.NULL;
final CarpetContext cc = (CarpetContext) c;
final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
if (inventoryLocator == null)
{
return Value.NULL;
}
ItemInput itemArg = null;
if (lv.size() > inventoryLocator.offset())
{
Value secondArg = lv.get(inventoryLocator.offset()+0);
final Value secondArg = lv.get(inventoryLocator.offset() + 0);
if (!secondArg.isNull())
{
itemArg = NBTSerializableValue.parseItem(secondArg.getString(), cc.registryAccess());
}
}
int startIndex = 0;
if (lv.size() > inventoryLocator.offset()+1)
if (lv.size() > inventoryLocator.offset() + 1)
{
startIndex = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset()+1)).getLong();
startIndex = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset() + 1)).getLong();
}
startIndex = NBTSerializableValue.validateSlot(startIndex, inventoryLocator.inventory());
for (int i = startIndex, maxi = inventoryLocator.inventory().getContainerSize(); i < maxi; i++)
{
ItemStack stack = inventoryLocator.inventory().getItem(i);
if ( (itemArg == null && stack.isEmpty()) || (itemArg != null && itemArg.getItem().equals(stack.getItem())) )
final ItemStack stack = inventoryLocator.inventory().getItem(i);
if ((itemArg == null && stack.isEmpty()) || (itemArg != null && itemArg.getItem().equals(stack.getItem())))
{
return new NumericValue(i);
}
}
return Value.NULL;
});
@@ -327,26 +334,36 @@ public class Inventories {
//inventory_remove(<b, e>, <item>, <amount=1>) -> bool
expression.addContextFunction("inventory_remove", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext) c;
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
if (inventoryLocator == null) return Value.NULL;
final CarpetContext cc = (CarpetContext) c;
final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
if (inventoryLocator == null)
{
return Value.NULL;
}
if (lv.size() <= inventoryLocator.offset())
{
throw new InternalExpressionException("'inventory_remove' requires at least an item to be removed");
ItemInput searchItem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset()).getString(), cc.registryAccess());
}
final ItemInput searchItem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset()).getString(), cc.registryAccess());
int amount = 1;
if (lv.size() > inventoryLocator.offset()+1)
amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset()+1)).getLong();
if (lv.size() > inventoryLocator.offset() + 1)
{
amount = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset() + 1)).getLong();
}
// not enough
if (((amount == 1) && (!inventoryLocator.inventory().hasAnyOf(Set.of(searchItem.getItem()))))
|| (inventoryLocator.inventory().countItem(searchItem.getItem()) < amount)) return Value.FALSE;
|| (inventoryLocator.inventory().countItem(searchItem.getItem()) < amount))
{
return Value.FALSE;
}
for (int i = 0, maxi = inventoryLocator.inventory().getContainerSize(); i < maxi; i++)
{
ItemStack stack = inventoryLocator.inventory().getItem(i);
if (stack.isEmpty())
final ItemStack stack = inventoryLocator.inventory().getItem(i);
if (stack.isEmpty() || !stack.getItem().equals(searchItem.getItem()))
{
continue;
if (!stack.getItem().equals(searchItem.getItem()))
continue;
int left = stack.getCount()-amount;
}
final int left = stack.getCount() - amount;
if (left > 0)
{
stack.setCount(left);
@@ -354,58 +371,78 @@ public class Inventories {
syncPlayerInventory(inventoryLocator, i);
return Value.TRUE;
}
else
{
inventoryLocator.inventory().removeItemNoUpdate(i);
syncPlayerInventory(inventoryLocator, i);
amount -= stack.getCount();
}
inventoryLocator.inventory().removeItemNoUpdate(i);
syncPlayerInventory(inventoryLocator, i);
amount -= stack.getCount();
}
if (amount > 0)
{
throw new InternalExpressionException("Something bad happened - cannot pull all items from inventory");
}
return Value.TRUE;
});
//inventory_drop(<b, e>, <n>, <amount=1, 0-whatever's there>) -> entity_item (and sets slot) or null if cannot
expression.addContextFunction("drop_item", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext) c;
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
if (inventoryLocator == null) return Value.NULL;
if (lv.size() == inventoryLocator.offset())
throw new InternalExpressionException("Slot number is required for inventory_drop");
int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset())).getLong();
slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory());
if (slot == inventoryLocator.inventory().getContainerSize()) return Value.NULL;
int amount = 0;
if (lv.size() > inventoryLocator.offset()+1)
amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset()+1)).getLong();
if (amount < 0)
throw new InternalExpressionException("Cannot throw negative number of items");
ItemStack stack = inventoryLocator.inventory().getItem(slot);
if (stack == null || stack.isEmpty()) return Value.ZERO;
if (amount == 0) amount = stack.getCount();
ItemStack droppedStack = inventoryLocator.inventory().removeItem(slot, amount);
if (droppedStack.isEmpty()) return Value.ZERO;
Object owner = inventoryLocator.owner();
ItemEntity item;
if (owner instanceof Player)
final CarpetContext cc = (CarpetContext) c;
final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
if (inventoryLocator == null)
{
item = ((Player) owner).drop(droppedStack, false, true);
return Value.NULL;
}
else if (owner instanceof LivingEntity villager)
if (lv.size() == inventoryLocator.offset())
{
throw new InternalExpressionException("Slot number is required for inventory_drop");
}
int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset())).getLong();
slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory());
if (slot == inventoryLocator.inventory().getContainerSize())
{
return Value.NULL;
}
int amount = 0;
if (lv.size() > inventoryLocator.offset() + 1)
{
amount = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset() + 1)).getLong();
}
if (amount < 0)
{
throw new InternalExpressionException("Cannot throw negative number of items");
}
final ItemStack stack = inventoryLocator.inventory().getItem(slot);
if (stack == null || stack.isEmpty())
{
return Value.ZERO;
}
if (amount == 0)
{
amount = stack.getCount();
}
final ItemStack droppedStack = inventoryLocator.inventory().removeItem(slot, amount);
if (droppedStack.isEmpty())
{
return Value.ZERO;
}
final Object owner = inventoryLocator.owner();
final ItemEntity item;
if (owner instanceof final Player player)
{
item = player.drop(droppedStack, false, true);
}
else if (owner instanceof LivingEntity livingEntity)
{
// stolen from LookTargetUtil.give((VillagerEntity)owner, droppedStack, (LivingEntity) owner);
double double_1 = villager.getY() - 0.30000001192092896D + villager.getEyeHeight();
item = new ItemEntity(villager.level, villager.getX(), double_1, villager.getZ(), droppedStack);
Vec3 vec3d_1 = villager.getViewVector(1.0F).normalize().scale(0.3);// new Vec3d(0, 0.3, 0);
item.setDeltaMovement(vec3d_1);
double double_1 = livingEntity.getY() - 0.30000001192092896D + livingEntity.getEyeHeight();
item = new ItemEntity(livingEntity.level, livingEntity.getX(), double_1, livingEntity.getZ(), droppedStack);
final Vec3 vec3d = livingEntity.getViewVector(1.0F).normalize().scale(0.3);// new Vec3d(0, 0.3, 0);
item.setDeltaMovement(vec3d);
item.setDefaultPickUpDelay();
cc.level().addFreshEntity(item);
}
else
{
Vec3 point = Vec3.atCenterOf(inventoryLocator.position()); //pos+0.5v
final Vec3 point = Vec3.atCenterOf(inventoryLocator.position()); //pos+0.5v
item = new ItemEntity(cc.level(), point.x, point.y, point.z, droppedStack);
item.setDefaultPickUpDelay();
cc.level().addFreshEntity(item);
@@ -413,49 +450,64 @@ public class Inventories {
return new NumericValue(item.getItem().getCount());
});
expression.addContextFunction("create_screen",-1, (c, t, lv) ->
expression.addContextFunction("create_screen", -1, (c, t, lv) ->
{
if(lv.size() < 3) throw new InternalExpressionException("'create_screen' requires at least three arguments");
Value playerValue = lv.get(0);
ServerPlayer player = EntityValue.getPlayerByValue(((CarpetContext) c).server(), playerValue);
if(player == null) throw new InternalExpressionException("'create_screen' requires a valid online player as the first argument.");
String type = lv.get(1).getString();
Component name = FormattedTextValue.getTextByValue(lv.get(2));
if (lv.size() < 3)
{
throw new InternalExpressionException("'create_screen' requires at least three arguments");
}
final Value playerValue = lv.get(0);
final ServerPlayer player = EntityValue.getPlayerByValue(((CarpetContext) c).server(), playerValue);
if (player == null)
{
throw new InternalExpressionException("'create_screen' requires a valid online player as the first argument.");
}
final String type = lv.get(1).getString();
final Component name = FormattedTextValue.getTextByValue(lv.get(2));
FunctionValue function = null;
if(lv.size() > 3)
if (lv.size() > 3)
{
function = FunctionArgument.findIn(c, expression.module, lv, 3, true, false).function;
}
return new ScreenValue(player,type,name,function,c);
return new ScreenValue(player, type, name, function, c);
});
expression.addContextFunction("close_screen",1, (c, t, lv) ->
expression.addContextFunction("close_screen", 1, (c, t, lv) ->
{
Value value = lv.get(0);
if(!(value instanceof ScreenValue screenValue)) throw new InternalExpressionException("'close_screen' requires a screen value as the first argument.");
if(!screenValue.isOpen()) return Value.FALSE;
final Value value = lv.get(0);
if (!(value instanceof final ScreenValue screenValue))
{
throw new InternalExpressionException("'close_screen' requires a screen value as the first argument.");
}
if (!screenValue.isOpen())
{
return Value.FALSE;
}
screenValue.close();
return Value.TRUE;
});
expression.addContextFunction("screen_property",-1, (c, t, lv) ->
expression.addContextFunction("screen_property", -1, (c, t, lv) ->
{
if(lv.size()<2) throw new InternalExpressionException("'screen_property' requires at least a screen and a property name");
if(!(lv.get(0) instanceof ScreenValue screenValue)) throw new InternalExpressionException("'screen_property' requires a screen value as the first argument");
String propertyName = lv.get(1).getString();
if(lv.size()>=3)
if (lv.size() < 2)
{
return screenValue.modifyProperty(propertyName,lv.subList(2,lv.size()));
throw new InternalExpressionException("'screen_property' requires at least a screen and a property name");
}
else
if (!(lv.get(0) instanceof final ScreenValue screenValue))
{
return screenValue.queryProperty(propertyName);
throw new InternalExpressionException("'screen_property' requires a screen value as the first argument");
}
final String propertyName = lv.get(1).getString();
return lv.size() >= 3
? screenValue.modifyProperty(propertyName, lv.subList(2, lv.size()))
: screenValue.queryProperty(propertyName);
});
}
private static void syncPlayerInventory(NBTSerializableValue.InventoryLocator inventory, int int_1)
private static void syncPlayerInventory(final NBTSerializableValue.InventoryLocator inventory, final int int_1)
{
if (inventory.owner() instanceof ServerPlayer player && !inventory.isEnder() && !(inventory.inventory() instanceof ScreenValue.ScreenHandlerInventory))
if (inventory.owner() instanceof final ServerPlayer player && !inventory.isEnder() && !(inventory.inventory() instanceof ScreenValue.ScreenHandlerInventory))
{
player.connection.send(new ClientboundContainerSetSlotPacket(
-2, 0, // resolve mystery argument
+30 -20
View File
@@ -1,6 +1,5 @@
package carpet.script.api;
import carpet.fakes.SpawnHelperInnerInterface;
import carpet.script.CarpetContext;
import carpet.script.Expression;
import carpet.script.exception.InternalExpressionException;
@@ -24,10 +23,11 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.NaturalSpawner;
public class Monitoring {
public class Monitoring
{
private static final Map<String, MobCategory> MOB_CATEGORY_MAP = Arrays.stream(MobCategory.values()).collect(Collectors.toMap(MobCategory::getName, Function.identity()));
public static void apply(Expression expression)
public static void apply(final Expression expression)
{
expression.addContextFunction("system_info", -1, (c, t, lv) ->
{
@@ -35,10 +35,14 @@ public class Monitoring {
{
return SystemInfo.getAll();
}
if (lv.size() == 1) {
String what = lv.get(0).getString();
Value res = SystemInfo.get(what, (CarpetContext) c);
if (res == null) throw new InternalExpressionException("Unknown option for 'system_info': " + what);
if (lv.size() == 1)
{
final String what = lv.get(0).getString();
final Value res = SystemInfo.get(what, (CarpetContext) c);
if (res == null)
{
throw new InternalExpressionException("Unknown option for 'system_info': " + what);
}
return res;
}
throw new InternalExpressionException("'system_info' requires one or no parameters");
@@ -46,18 +50,21 @@ public class Monitoring {
// game processed snooper functions
expression.addContextFunction("get_mob_counts", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
ServerLevel world = cc.level();
NaturalSpawner.SpawnState info = world.getChunkSource().getLastSpawnState();
if (info == null) return Value.NULL;
Object2IntMap<MobCategory> mobcounts = info.getMobCategoryCounts();
int chunks = info.getSpawnableChunkCount();
final CarpetContext cc = (CarpetContext) c;
final ServerLevel world = cc.level();
final NaturalSpawner.SpawnState info = world.getChunkSource().getLastSpawnState();
if (info == null)
{
return Value.NULL;
}
final Object2IntMap<MobCategory> mobcounts = info.getMobCategoryCounts();
final int chunks = info.getSpawnableChunkCount();
if (lv.size() == 0)
{
Map<Value, Value> retDict = new HashMap<>();
for (MobCategory category: mobcounts.keySet())
final Map<Value, Value> retDict = new HashMap<>();
for (final MobCategory category : mobcounts.keySet())
{
int currentCap = (int)(category.getMaxInstancesPerChunk() * chunks / SpawnReporter.MAGIC_NUMBER);
final int currentCap = category.getMaxInstancesPerChunk() * chunks / SpawnReporter.MAGIC_NUMBER;
retDict.put(
new StringValue(category.getSerializedName().toLowerCase(Locale.ROOT)),
ListValue.of(
@@ -67,12 +74,15 @@ public class Monitoring {
}
return MapValue.wrap(retDict);
}
String catString = lv.get(0).getString();
MobCategory cat = MOB_CATEGORY_MAP.get(catString.toLowerCase(Locale.ROOT));
if (cat == null) throw new InternalExpressionException("Unreconized mob category: "+catString);
final String catString = lv.get(0).getString();
final MobCategory cat = MOB_CATEGORY_MAP.get(catString.toLowerCase(Locale.ROOT));
if (cat == null)
{
throw new InternalExpressionException("Unreconized mob category: " + catString);
}
return ListValue.of(
new NumericValue(mobcounts.getInt(cat)),
new NumericValue((int)(cat.getMaxInstancesPerChunk() * chunks / SpawnReporter.MAGIC_NUMBER))
new NumericValue((int) (cat.getMaxInstancesPerChunk() * chunks / SpawnReporter.MAGIC_NUMBER))
);
});
}
+482 -282
View File
@@ -16,8 +16,10 @@ import carpet.script.value.StringValue;
import carpet.script.value.FormattedTextValue;
import carpet.script.value.Value;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
@@ -35,80 +37,90 @@ import net.minecraft.world.scores.Scoreboard;
import net.minecraft.world.scores.Team;
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
public class Scoreboards {
private static String getScoreboardKeyFromValue(Value keyValue)
public class Scoreboards
{
private static String getScoreboardKeyFromValue(final Value keyValue)
{
if (keyValue instanceof EntityValue)
if (keyValue instanceof final EntityValue ev)
{
Entity e = ((EntityValue) keyValue).getEntity();
if (e instanceof Player)
{
return e.getName().getString();
}
else
{
return e.getStringUUID();
}
}
else
{
return keyValue.getString();
final Entity e = ev.getEntity();
return e instanceof Player ? e.getName().getString() : e.getStringUUID();
}
return keyValue.getString();
}
public static void apply(Expression expression)
public static void apply(final Expression expression)
{
// scoreboard(player,'objective')
// scoreboard(player, objective, newValue)
expression.addContextFunction("scoreboard", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
Scoreboard scoreboard = cc.server().getScoreboard();
if (lv.size()==0)
return ListValue.wrap(scoreboard.getObjectiveNames().stream().map(StringValue::new));
String objectiveName = lv.get(0).getString();
Objective objective = scoreboard.getOrCreateObjective(objectiveName);
if (objective == null) return Value.NULL;
if (lv.size()==1)
return ListValue.wrap(scoreboard.getPlayerScores(objective).stream().map(s -> new StringValue(s.getOwner())));
String key = getScoreboardKeyFromValue(lv.get(1));
if(lv.size()==2)
final CarpetContext cc = (CarpetContext) c;
final Scoreboard scoreboard = cc.server().getScoreboard();
if (lv.size() == 0)
{
if(!scoreboard.hasPlayerScore(key, objective)) return Value.NULL;
return NumericValue.of(scoreboard.getOrCreatePlayerScore(key,objective).getScore());
return ListValue.wrap(scoreboard.getObjectiveNames().stream().map(StringValue::new));
}
final String objectiveName = lv.get(0).getString();
final Objective objective = scoreboard.getOrCreateObjective(objectiveName);
if (objective == null)
{
return Value.NULL;
}
if (lv.size() == 1)
{
return ListValue.wrap(scoreboard.getPlayerScores(objective).stream().map(s -> new StringValue(s.getOwner())));
}
final String key = getScoreboardKeyFromValue(lv.get(1));
if (lv.size() == 2)
{
return !scoreboard.hasPlayerScore(key, objective)
? Value.NULL
: NumericValue.of(scoreboard.getOrCreatePlayerScore(key, objective).getScore());
}
Value value = lv.get(2);
if(value.isNull()) {
Score score = scoreboard.getOrCreatePlayerScore(key, objective);
scoreboard.resetPlayerScore(key,objective);
final Value value = lv.get(2);
if (value.isNull())
{
final Score score = scoreboard.getOrCreatePlayerScore(key, objective);
scoreboard.resetPlayerScore(key, objective);
return NumericValue.of(score.getScore());
}
if (value instanceof NumericValue) {
Score score = scoreboard.getOrCreatePlayerScore(key, objective);
if (value instanceof NumericValue)
{
final Score score = scoreboard.getOrCreatePlayerScore(key, objective);
score.setScore(NumericValue.asNumber(value).getInt());
return NumericValue.of(score.getScore());
}
throw new InternalExpressionException("'scoreboard' requires a number or null as the third parameter");
});
expression.addContextFunction("scoreboard_remove", -1, (c, t, lv)->
expression.addContextFunction("scoreboard_remove", -1, (c, t, lv) ->
{
if (lv.size()==0) throw new InternalExpressionException("'scoreboard_remove' requires at least one parameter");
CarpetContext cc = (CarpetContext)c;
Scoreboard scoreboard = cc.server().getScoreboard();
String objectiveName = lv.get(0).getString();
Objective objective = scoreboard.getOrCreateObjective(objectiveName);
if (objective == null) return Value.FALSE;
if (lv.size() == 0)
{
throw new InternalExpressionException("'scoreboard_remove' requires at least one parameter");
}
final CarpetContext cc = (CarpetContext) c;
final Scoreboard scoreboard = cc.server().getScoreboard();
final String objectiveName = lv.get(0).getString();
final Objective objective = scoreboard.getOrCreateObjective(objectiveName);
if (objective == null)
{
return Value.FALSE;
}
if (lv.size() == 1)
{
scoreboard.removeObjective(objective);
return Value.TRUE;
}
String key = getScoreboardKeyFromValue(lv.get(1));
if (!scoreboard.hasPlayerScore(key, objective)) return Value.NULL;
Score scoreboardPlayerScore = scoreboard.getOrCreatePlayerScore(key, objective);
Value previous = new NumericValue(scoreboardPlayerScore.getScore());
final String key = getScoreboardKeyFromValue(lv.get(1));
if (!scoreboard.hasPlayerScore(key, objective))
{
return Value.NULL;
}
final Score scoreboardPlayerScore = scoreboard.getOrCreatePlayerScore(key, objective);
final Value previous = new NumericValue(scoreboardPlayerScore.getScore());
scoreboard.resetPlayerScore(key, objective);
return previous;
});
@@ -116,175 +128,247 @@ public class Scoreboards {
// objective_add('lvl','level')
// objective_add('counter')
expression.addContextFunction("scoreboard_add", -1, (c, t, lv)->
expression.addContextFunction("scoreboard_add", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
Scoreboard scoreboard = cc.server().getScoreboard();
if (lv.size() == 0 || lv.size()>2) throw new InternalExpressionException("'scoreboard_add' should have one or two parameters");
String objectiveName = lv.get(0).getString();
ObjectiveCriteria criterion;
if (lv.size() == 1 )
final CarpetContext cc = (CarpetContext) c;
final Scoreboard scoreboard = cc.server().getScoreboard();
if (lv.size() == 0 || lv.size() > 2)
{
throw new InternalExpressionException("'scoreboard_add' should have one or two parameters");
}
final String objectiveName = lv.get(0).getString();
final ObjectiveCriteria criterion;
if (lv.size() == 1)
{
criterion = ObjectiveCriteria.DUMMY;
}
else
{
String critetionName = lv.get(1).getString();
final String critetionName = lv.get(1).getString();
criterion = ObjectiveCriteria.byName(critetionName).orElse(null);
if (criterion==null)
if (criterion == null)
{
throw new ThrowStatement(critetionName, Throwables.UNKNOWN_CRITERION);
}
}
Objective objective = scoreboard.getOrCreateObjective(objectiveName);
if (objective != null) {
final Objective objective = scoreboard.getOrCreateObjective(objectiveName);
if (objective != null)
{
c.host.issueDeprecation("reading or modifying an objective's criterion with scoreboard_add");
if(lv.size() == 1) return StringValue.of(objective.getCriteria().getName());
if(objective.getCriteria().equals(criterion) || lv.size() == 1) return Value.NULL;
((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().get(objective.getCriteria()).remove(objective);
if (lv.size() == 1)
{
return StringValue.of(objective.getCriteria().getName());
}
if (objective.getCriteria().equals(criterion) || lv.size() == 1)
{
return Value.NULL;
}
((Scoreboard_scarpetMixin) scoreboard).getObjectivesByCriterion().get(objective.getCriteria()).remove(objective);
((Objective_scarpetMixin) objective).setCriterion(criterion);
(((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective);
(((Scoreboard_scarpetMixin) scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective);
scoreboard.onObjectiveAdded(objective);
return Value.FALSE;
}
scoreboard.addObjective(objectiveName, criterion, Component.literal(objectiveName), criterion.getDefaultRenderType());
return Value.TRUE;
});
expression.addContextFunction("scoreboard_property", -1, (c, t, lv) ->
{
if(lv.size() < 2) throw new InternalExpressionException("'scoreboard_property' requires at least two parameters");
CarpetContext cc = (CarpetContext)c;
Scoreboard scoreboard = cc.server().getScoreboard();
Objective objective = scoreboard.getOrCreateObjective(lv.get(0).getString());
if(objective == null) return Value.NULL;
if (lv.size() < 2)
{
throw new InternalExpressionException("'scoreboard_property' requires at least two parameters");
}
final CarpetContext cc = (CarpetContext) c;
final Scoreboard scoreboard = cc.server().getScoreboard();
final Objective objective = scoreboard.getOrCreateObjective(lv.get(0).getString());
if (objective == null)
{
return Value.NULL;
}
boolean modify = lv.size() > 2;
final boolean modify = lv.size() > 2;
Value setValue = null;
if(modify) {
if (modify)
{
setValue = lv.get(2);
}
String property = lv.get(1).getString();
switch (property) {
case "criterion":
if(modify) {
ObjectiveCriteria criterion = ObjectiveCriteria.byName(setValue.getString()).orElse(null);
if (criterion==null) throw new InternalExpressionException("Unknown scoreboard criterion: "+ setValue.getString());
if(objective.getCriteria().equals(criterion) || lv.size() == 1) return Value.FALSE;
((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().get(objective.getCriteria()).remove(objective);
final String property = lv.get(1).getString();
switch (property)
{
case "criterion" -> {
if (modify)
{
final ObjectiveCriteria criterion = ObjectiveCriteria.byName(setValue.getString()).orElse(null);
if (criterion == null)
{
throw new InternalExpressionException("Unknown scoreboard criterion: " + setValue.getString());
}
if (objective.getCriteria().equals(criterion) || lv.size() == 1)
{
return Value.FALSE;
}
((Scoreboard_scarpetMixin) scoreboard).getObjectivesByCriterion().get(objective.getCriteria()).remove(objective);
((Objective_scarpetMixin) objective).setCriterion(criterion);
(((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective);
(((Scoreboard_scarpetMixin) scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective);
scoreboard.onObjectiveAdded(objective);
return Value.TRUE;
}
return StringValue.of(objective.getCriteria().getName());
case "display_name":
if(modify) {
Component text = FormattedTextValue.getTextByValue(setValue);
}
case "display_name" -> {
if (modify)
{
final Component text = FormattedTextValue.getTextByValue(setValue);
objective.setDisplayName(text);
return Value.TRUE;
}
return new FormattedTextValue(objective.getDisplayName());
case "display_slot":
if(modify) {
int slotId = Scoreboard.getDisplaySlotByName(setValue.getString());
if(slotId == -1) throw new InternalExpressionException("Unknown scoreboard display slot: " + setValue.getString());
if(objective.equals(scoreboard.getDisplayObjective(slotId))) {
}
case "display_slot" -> {
if (modify)
{
final int slotId = Scoreboard.getDisplaySlotByName(setValue.getString());
if (slotId == -1)
{
throw new InternalExpressionException("Unknown scoreboard display slot: " + setValue.getString());
}
if (objective.equals(scoreboard.getDisplayObjective(slotId)))
{
return Value.FALSE;
}
scoreboard.setDisplayObjective(slotId,objective);
scoreboard.setDisplayObjective(slotId, objective);
return Value.TRUE;
}
List<Value> slots = new ArrayList<>();
for(int i = 0; i < 19; i++) {
if (scoreboard.getDisplayObjective(i) == objective) {
String slotName = Scoreboard.getDisplaySlotName(i);
final List<Value> slots = new ArrayList<>();
for (int i = 0; i < 19; i++)
{
if (scoreboard.getDisplayObjective(i) == objective)
{
final String slotName = Scoreboard.getDisplaySlotName(i);
slots.add(StringValue.of(slotName));
}
}
return ListValue.wrap(slots);
case "render_type":
if(modify) {
ObjectiveCriteria.RenderType renderType = ObjectiveCriteria.RenderType.byId(setValue.getString().toLowerCase());
if(objective.getRenderType().equals(renderType)) return Value.FALSE;
}
case "render_type" -> {
if (modify)
{
final ObjectiveCriteria.RenderType renderType = ObjectiveCriteria.RenderType.byId(setValue.getString().toLowerCase());
if (objective.getRenderType().equals(renderType))
{
return Value.FALSE;
}
objective.setRenderType(renderType);
return Value.TRUE;
}
return StringValue.of(objective.getRenderType().getId());
default:
throw new InternalExpressionException("scoreboard property '" + property + "' is not a valid property");
}
default -> throw new InternalExpressionException("scoreboard property '" + property + "' is not a valid property");
}
});
expression.addContextFunction("scoreboard_display", 2, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
Scoreboard scoreboard = cc.server().getScoreboard();
String location = lv.get(0).getString();
int slot = Scoreboard.getDisplaySlotByName(location);
if (slot < 0) throw new InternalExpressionException("Invalid objective slot: "+location);
Value target = lv.get(1);
final CarpetContext cc = (CarpetContext) c;
final Scoreboard scoreboard = cc.server().getScoreboard();
final String location = lv.get(0).getString();
final int slot = Scoreboard.getDisplaySlotByName(location);
if (slot < 0)
{
throw new InternalExpressionException("Invalid objective slot: " + location);
}
final Value target = lv.get(1);
if (target.isNull())
{
scoreboard.setDisplayObjective(slot, null);
return new NumericValue(slot);
}
String objectiveString = target.getString();
Objective objective = scoreboard.getOrCreateObjective(objectiveString);
if (objective == null) return Value.NULL;
final String objectiveString = target.getString();
final Objective objective = scoreboard.getOrCreateObjective(objectiveString);
if (objective == null)
{
return Value.NULL;
}
scoreboard.setDisplayObjective(slot, objective);
return new NumericValue(slot);
});
expression.addContextFunction("team_list", -1, (c, t, lv) ->
{
if(lv.size() > 1) throw new InternalExpressionException("'team_list' requires zero or one parameters");
CarpetContext cc = (CarpetContext)c;
ServerScoreboard scoreboard = cc.server().getScoreboard();
if(lv.size() == 0)
if (lv.size() > 1)
{
throw new InternalExpressionException("'team_list' requires zero or one parameters");
}
final CarpetContext cc = (CarpetContext) c;
final ServerScoreboard scoreboard = cc.server().getScoreboard();
if (lv.size() == 0)
{
return ListValue.wrap(scoreboard.getTeamNames().stream().map(StringValue::of));
if (lv.size() != 1) return Value.NULL;
PlayerTeam team = scoreboard.getPlayerTeam(lv.get(0).getString());
if(team == null) return Value.NULL;
return ListValue.wrap(team.getPlayers().stream().map(StringValue::of));
}
if (lv.size() != 1)
{
return Value.NULL;
}
final PlayerTeam team = scoreboard.getPlayerTeam(lv.get(0).getString());
return team == null ? Value.NULL : ListValue.wrap(team.getPlayers().stream().map(StringValue::of));
});
expression.addContextFunction("team_add", -1, (c, t, lv) ->
{
if(!(lv.size() < 3 && lv.size() > 0)) throw new InternalExpressionException("'team_add' requires one or two parameters");
CarpetContext cc = (CarpetContext)c;
ServerScoreboard scoreboard = cc.server().getScoreboard();
String teamName = lv.get(0).getString();
if(lv.size() == 1)
if (!(lv.size() < 3 && lv.size() > 0))
{
if (scoreboard.getPlayerTeam(teamName) != null) return Value.NULL;
throw new InternalExpressionException("'team_add' requires one or two parameters");
}
final CarpetContext cc = (CarpetContext) c;
final ServerScoreboard scoreboard = cc.server().getScoreboard();
final String teamName = lv.get(0).getString();
if (lv.size() == 1)
{
if (scoreboard.getPlayerTeam(teamName) != null)
{
return Value.NULL;
}
scoreboard.addPlayerTeam(teamName);
return new StringValue(teamName);
}
if(lv.size() != 2) return Value.NULL;
Value playerVal = lv.get(1);
String player = EntityValue.getPlayerNameByValue(playerVal);
if(player == null) return Value.NULL;
PlayerTeam team = scoreboard.getPlayerTeam(teamName);
if(team == null) return Value.NULL;
if(team.isAlliedTo(scoreboard.getPlayersTeam(player))) return Value.FALSE;
scoreboard.addPlayerToTeam(player,scoreboard.getPlayerTeam(teamName));
if (lv.size() != 2)
{
return Value.NULL;
}
final Value playerVal = lv.get(1);
final String player = EntityValue.getPlayerNameByValue(playerVal);
if (player == null)
{
return Value.NULL;
}
final PlayerTeam team = scoreboard.getPlayerTeam(teamName);
if (team == null)
{
return Value.NULL;
}
if (team.isAlliedTo(scoreboard.getPlayersTeam(player)))
{
return Value.FALSE;
}
scoreboard.addPlayerToTeam(player, scoreboard.getPlayerTeam(teamName));
return Value.TRUE;
});
expression.addContextFunction("team_remove", 1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
ServerScoreboard scoreboard = cc.server().getScoreboard();
Value teamVal = lv.get(0);
String team = teamVal.getString();
if(scoreboard.getPlayerTeam(team) == null) return Value.NULL;
final CarpetContext cc = (CarpetContext) c;
final ServerScoreboard scoreboard = cc.server().getScoreboard();
final Value teamVal = lv.get(0);
final String team = teamVal.getString();
if (scoreboard.getPlayerTeam(team) == null)
{
return Value.NULL;
}
scoreboard.removePlayerTeam(scoreboard.getPlayerTeam(team));
return Value.TRUE;
});
@@ -292,212 +376,328 @@ public class Scoreboards {
expression.addContextFunction("team_leave", 1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
ServerScoreboard scoreboard = cc.server().getScoreboard();
Value playerVal = lv.get(0);
String player = EntityValue.getPlayerNameByValue(playerVal);
if(player == null) return Value.NULL;
return BooleanValue.of(scoreboard.removePlayerFromTeam(player));
final CarpetContext cc = (CarpetContext) c;
final ServerScoreboard scoreboard = cc.server().getScoreboard();
final Value playerVal = lv.get(0);
final String player = EntityValue.getPlayerNameByValue(playerVal);
return player == null ? Value.NULL : BooleanValue.of(scoreboard.removePlayerFromTeam(player));
});
expression.addContextFunction("team_property", -1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
ServerScoreboard scoreboard = cc.server().getScoreboard();
if(lv.size() < 2 || lv.size() > 3) throw new InternalExpressionException("'team_property' requires two or three arguments");
Value teamVal = lv.get(0);
Value propertyVal = lv.get(1);
final CarpetContext cc = (CarpetContext) c;
final ServerScoreboard scoreboard = cc.server().getScoreboard();
if (lv.size() < 2 || lv.size() > 3)
{
throw new InternalExpressionException("'team_property' requires two or three arguments");
}
final Value teamVal = lv.get(0);
final Value propertyVal = lv.get(1);
Value settingVal = null;
boolean modifying = false;
if(lv.size() == 3)
if (lv.size() == 3)
{
modifying = true;
settingVal = lv.get(2);
}
PlayerTeam team = scoreboard.getPlayerTeam(teamVal.getString());
if(team == null) return Value.NULL;
final PlayerTeam team = scoreboard.getPlayerTeam(teamVal.getString());
if (team == null)
{
return Value.NULL;
}
if(!(propertyVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the second argument");
if (!(propertyVal instanceof StringValue))
{
throw new InternalExpressionException("'team_property' requires a string as the second argument");
}
switch (propertyVal.getString()) {
case "collisionRule":
if(!modifying) return new StringValue(team.getCollisionRule().name);
if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString());
Team.CollisionRule collisionRule = Team.CollisionRule.byName(settingVal.getString());
if(collisionRule == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString());
switch (propertyVal.getString())
{
case "collisionRule" -> {
if (!modifying)
{
return new StringValue(team.getCollisionRule().name);
}
if (!(settingVal instanceof StringValue))
{
throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString());
}
final Team.CollisionRule collisionRule = Team.CollisionRule.byName(settingVal.getString());
if (collisionRule == null)
{
throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString());
}
team.setCollisionRule(collisionRule);
break;
case "color":
if(!modifying) return new StringValue(team.getColor().getName());
if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString());
ChatFormatting color = ChatFormatting.getByName(settingVal.getString().toUpperCase());
if(color == null || !color.isColor()) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString());
}
case "color" -> {
if (!modifying)
{
return new StringValue(team.getColor().getName());
}
if (!(settingVal instanceof StringValue))
{
throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString());
}
final ChatFormatting color = ChatFormatting.getByName(settingVal.getString().toUpperCase());
if (color == null || !color.isColor())
{
throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString());
}
team.setColor(color);
break;
case "deathMessageVisibility":
if(!modifying) return new StringValue(team.getDeathMessageVisibility().name);
if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString());
Team.Visibility deathMessageVisibility = Team.Visibility.byName(settingVal.getString());
if(deathMessageVisibility == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString());
}
case "deathMessageVisibility" -> {
if (!modifying)
{
return new StringValue(team.getDeathMessageVisibility().name);
}
if (!(settingVal instanceof StringValue))
{
throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString());
}
final Team.Visibility deathMessageVisibility = Team.Visibility.byName(settingVal.getString());
if (deathMessageVisibility == null)
{
throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString());
}
team.setDeathMessageVisibility(deathMessageVisibility);
break;
case "displayName":
if(!modifying) return new FormattedTextValue(team.getDisplayName());
if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString());
Component displayName;
displayName = FormattedTextValue.getTextByValue(settingVal);
team.setDisplayName(displayName);
break;
case "friendlyFire":
if(!modifying) return BooleanValue.of(team.isAllowFriendlyFire());
if(!(settingVal instanceof NumericValue)) throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString());
boolean friendlyFire = settingVal.getBoolean();
team.setAllowFriendlyFire(friendlyFire);
break;
case "nametagVisibility":
if(!modifying) return new StringValue(team.getNameTagVisibility().name);
if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString());
Team.Visibility nametagVisibility = Team.Visibility.byName(settingVal.getString());
if(nametagVisibility == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString());
}
case "displayName" -> {
if (!modifying)
{
return new FormattedTextValue(team.getDisplayName());
}
if (!(settingVal instanceof StringValue))
{
throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString());
}
team.setDisplayName(FormattedTextValue.getTextByValue(settingVal));
}
case "friendlyFire" -> {
if (!modifying)
{
return BooleanValue.of(team.isAllowFriendlyFire());
}
if (!(settingVal instanceof NumericValue))
{
throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString());
}
team.setAllowFriendlyFire(settingVal.getBoolean());
}
case "nametagVisibility" -> {
if (!modifying)
{
return new StringValue(team.getNameTagVisibility().name);
}
if (!(settingVal instanceof StringValue))
{
throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString());
}
final Team.Visibility nametagVisibility = Team.Visibility.byName(settingVal.getString());
if (nametagVisibility == null)
{
throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString());
}
team.setNameTagVisibility(nametagVisibility);
break;
case "prefix":
if(!modifying) return new FormattedTextValue(team.getPlayerPrefix());
if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property ' requires a string or formatted text as the third argument for the property " + propertyVal.getString());
Component prefix;
prefix = FormattedTextValue.getTextByValue(settingVal);
team.setPlayerPrefix(prefix);
break;
case "seeFriendlyInvisibles":
if(!modifying) return BooleanValue.of(team.canSeeFriendlyInvisibles());
if(!(settingVal instanceof NumericValue)) throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString());
boolean seeFriendlyInvisibles = settingVal.getBoolean();
team.setSeeFriendlyInvisibles(seeFriendlyInvisibles);
break;
case "suffix":
if(!modifying) return new FormattedTextValue(team.getPlayerSuffix());
if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString());
Component suffix;
suffix = FormattedTextValue.getTextByValue(settingVal);
team.setPlayerSuffix(suffix);
break;
default:
throw new InternalExpressionException("team property '" + propertyVal.getString() + "' is not a valid property");
}
case "prefix" -> {
if (!modifying)
{
return new FormattedTextValue(team.getPlayerPrefix());
}
if (!(settingVal instanceof StringValue))
{
throw new InternalExpressionException("'team_property ' requires a string or formatted text as the third argument for the property " + propertyVal.getString());
}
team.setPlayerPrefix(FormattedTextValue.getTextByValue(settingVal));
}
case "seeFriendlyInvisibles" -> {
if (!modifying)
{
return BooleanValue.of(team.canSeeFriendlyInvisibles());
}
if (!(settingVal instanceof NumericValue))
{
throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString());
}
team.setSeeFriendlyInvisibles(settingVal.getBoolean());
}
case "suffix" -> {
if (!modifying)
{
return new FormattedTextValue(team.getPlayerSuffix());
}
if (!(settingVal instanceof StringValue))
{
throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString());
}
team.setPlayerSuffix(FormattedTextValue.getTextByValue(settingVal));
}
default -> throw new InternalExpressionException("team property '" + propertyVal.getString() + "' is not a valid property");
}
return Value.TRUE;
});
expression.addContextFunction("bossbar", -1, (c, t, lv) ->
{
CustomBossEvents bossBarManager = ((CarpetContext)c).server().getCustomBossEvents();
if(lv.size() > 3) throw new InternalExpressionException("'bossbar' accepts max three arguments");
if(lv.size() == 0) return ListValue.wrap(bossBarManager.getEvents().stream().map(CustomBossEvent::getTextId).map(ResourceLocation::toString).map(StringValue::of));
String id = lv.get(0).getString();
ResourceLocation identifier;
identifier = InputValidator.identifierOf(id);
if(lv.size() == 1)
final CustomBossEvents bossBarManager = ((CarpetContext) c).server().getCustomBossEvents();
if (lv.size() > 3)
{
if(bossBarManager.get(identifier) != null) return Value.FALSE;
return StringValue.of(bossBarManager.create(identifier,Component.literal(id)).getTextId().toString());
throw new InternalExpressionException("'bossbar' accepts max three arguments");
}
String property = lv.get(1).getString();
if (lv.size() == 0)
{
return ListValue.wrap(bossBarManager.getEvents().stream().map(CustomBossEvent::getTextId).map(ResourceLocation::toString).map(StringValue::of));
}
CustomBossEvent bossBar = bossBarManager.get(identifier);
if(bossBar == null) return Value.NULL;
final String id = lv.get(0).getString();
final ResourceLocation identifier = InputValidator.identifierOf(id);
Value propertyValue = (lv.size() == 3)?lv.get(2):null;
if (lv.size() == 1)
{
if (bossBarManager.get(identifier) != null)
{
return Value.FALSE;
}
return StringValue.of(bossBarManager.create(identifier, Component.literal(id)).getTextId().toString());
}
switch (property) {
case "color":
if(propertyValue == null) {
BossEvent.BossBarColor color = (bossBar).getColor();
if(color == null) return Value.NULL;
return StringValue.of(color.getName());
final String property = lv.get(1).getString();
final CustomBossEvent bossBar = bossBarManager.get(identifier);
if (bossBar == null)
{
return Value.NULL;
}
final Value propertyValue = (lv.size() == 3) ? lv.get(2) : null;
switch (property)
{
case "color" -> {
if (propertyValue == null)
{
final BossEvent.BossBarColor color = (bossBar).getColor();
return color == null ? Value.NULL : StringValue.of(color.getName());
}
final BossEvent.BossBarColor color = BossEvent.BossBarColor.byName(propertyValue.getString());
if (color == null)
{
return Value.NULL;
}
BossEvent.BossBarColor color = BossEvent.BossBarColor.byName(propertyValue.getString());
if(color == null) return Value.NULL;
bossBar.setColor(BossEvent.BossBarColor.byName(propertyValue.getString()));
return Value.TRUE;
case "max":
if(propertyValue == null) return NumericValue.of(bossBar.getMax());
if(!(propertyValue instanceof NumericValue)) throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property);
bossBar.setMax(((NumericValue) propertyValue).getInt());
}
case "max" -> {
if (propertyValue == null)
{
return NumericValue.of(bossBar.getMax());
}
if (!(propertyValue instanceof final NumericValue number))
{
throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property);
}
bossBar.setMax(number.getInt());
return Value.TRUE;
case "name":
if(propertyValue == null) return new FormattedTextValue(bossBar.getName());
}
case "name" -> {
if (propertyValue == null)
{
return new FormattedTextValue(bossBar.getName());
}
bossBar.setName(FormattedTextValue.getTextByValue(propertyValue));
return Value.TRUE;
case "add_player":
if(propertyValue == null) throw new InternalExpressionException("Bossbar property " + property + " can't be queried, add a third parameter");
if(propertyValue instanceof ListValue) {
((ListValue) propertyValue).getItems().forEach((v)->{
ServerPlayer player = EntityValue.getPlayerByValue(((CarpetContext)c).server(), propertyValue);
if(player != null) bossBar.addPlayer(player);
}
case "add_player" -> {
if (propertyValue == null)
{
throw new InternalExpressionException("Bossbar property " + property + " can't be queried, add a third parameter");
}
if (propertyValue instanceof final ListValue list)
{
list.getItems().forEach((v) -> {
final ServerPlayer player = EntityValue.getPlayerByValue(((CarpetContext) c).server(), propertyValue);
if (player != null)
{
bossBar.addPlayer(player);
}
});
return Value.TRUE;
}
ServerPlayer player = EntityValue.getPlayerByValue(((CarpetContext) c).server(), propertyValue);
if(player != null) {
final ServerPlayer player = EntityValue.getPlayerByValue(((CarpetContext) c).server(), propertyValue);
if (player != null)
{
bossBar.addPlayer(player);
return Value.TRUE;
}
return Value.FALSE;
case "players":
if (propertyValue == null) return ListValue.wrap(bossBar.getPlayers().stream().map(EntityValue::new));
if(propertyValue instanceof ListValue)
}
case "players" -> {
if (propertyValue == null)
{
return ListValue.wrap(bossBar.getPlayers().stream().map(EntityValue::new));
}
if (propertyValue instanceof final ListValue list)
{
bossBar.removeAllPlayers();
((ListValue) propertyValue).getItems().forEach((v) -> {
list.getItems().forEach(v -> {
ServerPlayer p = EntityValue.getPlayerByValue(((CarpetContext) c).server(), v);
if (p != null) bossBar.addPlayer(p);
if (p != null)
{
bossBar.addPlayer(p);
}
});
return Value.TRUE;
}
ServerPlayer p = EntityValue.getPlayerByValue(((CarpetContext) c).server(), propertyValue);
final ServerPlayer p = EntityValue.getPlayerByValue(((CarpetContext) c).server(), propertyValue);
bossBar.removeAllPlayers();
if (p != null) {
if (p != null)
{
bossBar.addPlayer(p);
return Value.TRUE;
}
return Value.FALSE;
case "style":
if(propertyValue == null) return StringValue.of(bossBar.getOverlay().getName());
BossEvent.BossBarOverlay style = BossEvent.BossBarOverlay.byName(propertyValue.getString());
if(style == null) throw new InternalExpressionException("'" + propertyValue.getString() + "' is not a valid value for property " + property);
}
case "style" -> {
if (propertyValue == null)
{
return StringValue.of(bossBar.getOverlay().getName());
}
final BossEvent.BossBarOverlay style = BossEvent.BossBarOverlay.byName(propertyValue.getString());
if (style == null)
{
throw new InternalExpressionException("'" + propertyValue.getString() + "' is not a valid value for property " + property);
}
bossBar.setOverlay(style);
return Value.TRUE;
case "value":
if(propertyValue == null) return NumericValue.of(bossBar.getValue());
if(!(propertyValue instanceof NumericValue)) throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property);
bossBar.setValue(((NumericValue) propertyValue).getInt());
}
case "value" -> {
if (propertyValue == null)
{
return NumericValue.of(bossBar.getValue());
}
if (!(propertyValue instanceof final NumericValue number))
{
throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property);
}
bossBar.setValue(number.getInt());
return Value.TRUE;
case "visible":
if(propertyValue == null) return BooleanValue.of(bossBar.isVisible());
}
case "visible" -> {
if (propertyValue == null)
{
return BooleanValue.of(bossBar.isVisible());
}
bossBar.setVisible(propertyValue.getBoolean());
return Value.TRUE;
case "remove":
}
case "remove" -> {
bossBarManager.remove(bossBar);
return Value.TRUE;
default:
throw new InternalExpressionException("Unknown bossbar property " + property);
}
default -> throw new InternalExpressionException("Unknown bossbar property " + property);
}
});
}
+23 -16
View File
@@ -16,21 +16,28 @@ public class Threading
{
//"overidden" native call to cancel if on main thread
expression.addContextFunction("task_join", 1, (c, t, lv) -> {
if (((CarpetContext)c).server().isSameThread())
if (((CarpetContext) c).server().isSameThread())
{
throw new InternalExpressionException("'task_join' cannot be called from main thread to avoid deadlocks");
Value v = lv.get(0);
if (!(v instanceof ThreadValue))
}
final Value v = lv.get(0);
if (!(v instanceof final ThreadValue tv))
{
throw new InternalExpressionException("'task_join' could only be used with a task value");
return ((ThreadValue) v).join();
}
return tv.join();
});
// has to be lazy due to deferred execution of the expression
expression.addLazyFunctionWithDelegation("task_dock", 1, false,true, (c, t, expr, tok, lv) -> {
CarpetContext cc = (CarpetContext)c;
MinecraftServer server = cc.server();
if (server.isSameThread()) return lv.get(0); // pass through for on thread tasks
Value[] result = new Value[]{Value.NULL};
RuntimeException[] internal = new RuntimeException[]{null};
expression.addLazyFunctionWithDelegation("task_dock", 1, false, true, (c, t, expr, tok, lv) -> {
final CarpetContext cc = (CarpetContext) c;
final MinecraftServer server = cc.server();
if (server.isSameThread())
{
return lv.get(0); // pass through for on thread tasks
}
final Value[] result = new Value[]{Value.NULL};
final RuntimeException[] internal = new RuntimeException[]{null};
try
{
((CarpetContext) c).server().executeBlocking(() ->
@@ -39,22 +46,22 @@ public class Threading
{
result[0] = lv.get(0).evalValue(c, t);
}
catch (ExpressionException exc)
catch (final ExpressionException exc)
{
internal[0] = exc;
}
catch (InternalExpressionException exc)
catch (final InternalExpressionException exc)
{
internal[0] = new ExpressionException(c, expr, tok, exc.getMessage(), exc.stack);
}
catch (ArithmeticException exc)
catch (final ArithmeticException exc)
{
internal[0] = new ExpressionException(c, expr, tok, "Your math is wrong, "+exc.getMessage());
internal[0] = new ExpressionException(c, expr, tok, "Your math is wrong, " + exc.getMessage());
}
});
}
catch (CompletionException exc)
catch (final CompletionException exc)
{
throw new InternalExpressionException("Error while executing docked task section, internal stack trace is gone");
}
@@ -62,7 +69,7 @@ public class Threading
{
throw internal[0];
}
Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later
final Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later
return (_c, _t) -> ret;
// pass through placeholder
// implmenetation should dock the task on the main thread.
File diff suppressed because it is too large. Load diff