semi-auto cleanup
This commit is contained in:
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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
Reference in new issue
Block a user