Merge branch 'master' into light
# Conflicts: # src/main/resources/carpet.accesswidener # src/main/resources/fabric.mod.json
This commit is contained in:
commit
7067e59a21
66 files changed
+1898
-495
No files matched your search
@@ -488,6 +488,37 @@ public class CarpetEventServer
|
||||
handler.call( () -> Collections.singletonList(((c, t) -> new EntityValue(player))), player::getCommandSource);
|
||||
}
|
||||
},
|
||||
PLAYER_CHOOSES_RECIPE("player_chooses_recipe", 3, false)
|
||||
{
|
||||
@Override
|
||||
public void onRecipeSelected(ServerPlayerEntity player, Identifier recipe, boolean fullStack)
|
||||
{
|
||||
handler.call( () ->
|
||||
{
|
||||
return Arrays.asList(
|
||||
((c, t) -> new EntityValue(player)),
|
||||
((c, t) -> new StringValue(NBTSerializableValue.nameFromRegistryId(recipe))),
|
||||
((c, t) -> new NumericValue(fullStack))
|
||||
);
|
||||
}, player::getCommandSource);
|
||||
}
|
||||
},
|
||||
PLAYER_SWITCHES_SLOT("player_switches_slot", 3, false)
|
||||
{
|
||||
@Override
|
||||
public void onSlotSwitch(ServerPlayerEntity player, int from, int to)
|
||||
{
|
||||
if (from == to) return; // initial slot update
|
||||
handler.call( () ->
|
||||
{
|
||||
return Arrays.asList(
|
||||
((c, t) -> new EntityValue(player)),
|
||||
((c, t) -> new NumericValue(from)),
|
||||
((c, t) -> new NumericValue(to))
|
||||
);
|
||||
}, player::getCommandSource);
|
||||
}
|
||||
},
|
||||
PLAYER_TAKES_DAMAGE("player_takes_damage", 4, false)
|
||||
{
|
||||
@Override
|
||||
@@ -647,6 +678,8 @@ public class CarpetEventServer
|
||||
public void onEntityAction(ServerPlayerEntity player, Entity entity, Hand enumhand) { }
|
||||
public void onDimensionChange(ServerPlayerEntity player, Vec3d from, Vec3d to, DimensionType fromDim, DimensionType dimTo) {}
|
||||
public void onDamage(Entity target, float amount, DamageSource source) { }
|
||||
public void onRecipeSelected(ServerPlayerEntity player, Identifier recipe, boolean fullStack) {}
|
||||
public void onSlotSwitch(ServerPlayerEntity player, int from, int to) {}
|
||||
|
||||
|
||||
public void onWorldEvent(ServerWorld world, BlockPos pos) { }
|
||||
|
||||
@@ -2,8 +2,10 @@ package carpet.script;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.fakes.ChunkTicketManagerInterface;
|
||||
import carpet.fakes.IngredientInterface;
|
||||
import carpet.fakes.MinecraftServerInterface;
|
||||
import carpet.fakes.BiomeArrayInterface;
|
||||
import carpet.fakes.RecipeManagerInterface;
|
||||
import carpet.fakes.ServerChunkManagerInterface;
|
||||
import carpet.fakes.ServerLightingProviderInterface;
|
||||
import carpet.fakes.StatTypeInterface;
|
||||
@@ -81,6 +83,13 @@ import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.particle.ParticleEffect;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.recipe.AbstractCookingRecipe;
|
||||
import net.minecraft.recipe.CuttingRecipe;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.recipe.ShapedRecipe;
|
||||
import net.minecraft.recipe.ShapelessRecipe;
|
||||
import net.minecraft.recipe.SpecialCraftingRecipe;
|
||||
import net.minecraft.scoreboard.Scoreboard;
|
||||
import net.minecraft.scoreboard.ScoreboardCriterion;
|
||||
import net.minecraft.scoreboard.ScoreboardObjective;
|
||||
@@ -97,6 +106,7 @@ import net.minecraft.stat.Stat;
|
||||
import net.minecraft.stat.StatType;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.Property;
|
||||
import net.minecraft.structure.StructureFeatures;
|
||||
import net.minecraft.structure.StructurePiece;
|
||||
import net.minecraft.structure.StructureStart;
|
||||
import net.minecraft.text.LiteralText;
|
||||
@@ -111,9 +121,11 @@ import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.EulerAngle;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.gen.feature.Feature;
|
||||
import net.minecraft.world.gen.feature.StructureFeature;
|
||||
import net.minecraft.world.poi.PointOfInterest;
|
||||
@@ -130,8 +142,10 @@ import net.minecraft.world.dimension.DimensionType;
|
||||
import net.minecraft.world.gen.ChunkRandom;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
@@ -342,6 +356,18 @@ public class CarpetExpression
|
||||
return MapValue.wrap(ret);
|
||||
}
|
||||
|
||||
private static long lastSeed = -1;
|
||||
private void BooYah(ChunkGenerator generator)
|
||||
{
|
||||
synchronized (generator)
|
||||
{
|
||||
if (generator.getSeed() != lastSeed)
|
||||
{
|
||||
StructureFeatures.STRONGHOLD.shouldStartAt(null, generator, null, 0, 0, null);
|
||||
lastSeed = generator.getSeed();
|
||||
}
|
||||
}
|
||||
}
|
||||
private void API_BlockManipulation()
|
||||
{
|
||||
this.expr.addLazyFunction("block", -1, (c, t, lv) ->
|
||||
@@ -737,43 +763,76 @@ public class CarpetExpression
|
||||
this.expr.addLazyFunction("without_updates", 1, (c, t, lv) ->
|
||||
{
|
||||
boolean previous = CarpetSettings.impendingFillSkipUpdates;
|
||||
try
|
||||
if (previous) return lv.get(0);
|
||||
Value [] result = new Value[]{Value.NULL};
|
||||
((CarpetContext)c).s.getMinecraftServer().submitAndJoin( () ->
|
||||
{
|
||||
CarpetSettings.impendingFillSkipUpdates = true;
|
||||
Value ret = lv.get(0).evalValue(c, t);
|
||||
return (cc, tt) -> ret;
|
||||
}
|
||||
finally
|
||||
{
|
||||
CarpetSettings.impendingFillSkipUpdates = previous;
|
||||
}
|
||||
try
|
||||
{
|
||||
CarpetSettings.impendingFillSkipUpdates = true;
|
||||
result[0] = lv.get(0).evalValue(c, t);
|
||||
}
|
||||
finally
|
||||
{
|
||||
CarpetSettings.impendingFillSkipUpdates = previous;
|
||||
}
|
||||
});
|
||||
return (cc, tt) -> result[0];
|
||||
});
|
||||
|
||||
this.expr.addLazyFunction("set", -1, (c, t, lv) ->
|
||||
{
|
||||
CarpetContext cc = (CarpetContext)c;
|
||||
ServerWorld world = cc.s.getWorld();
|
||||
if (lv.size() < 2 || lv.size() % 2 == 1)
|
||||
throw new InternalExpressionException("'set' should have at least 2 params and odd attributes");
|
||||
BlockArgument targetLocator = BlockArgument.findIn(cc, lv, 0);
|
||||
BlockArgument sourceLocator = BlockArgument.findIn(cc, lv, targetLocator.offset, true);
|
||||
BlockState sourceBlockState = sourceLocator.block.getBlockState();
|
||||
BlockState targetBlockState = world.getBlockState(targetLocator.block.getPos());
|
||||
if (sourceLocator.offset < lv.size())
|
||||
CompoundTag data = null;
|
||||
if (lv.size() > sourceLocator.offset)
|
||||
{
|
||||
StateManager<Block, BlockState> states = sourceBlockState.getBlock().getStateManager();
|
||||
for (int i = sourceLocator.offset; i < lv.size(); i += 2)
|
||||
List<Value> args = new ArrayList<>();
|
||||
for (int i = sourceLocator.offset, m = lv.size(); i < m; i++)
|
||||
{
|
||||
String paramString = lv.get(i).evalValue(c).getString();
|
||||
args.add(lv.get(i).evalValue(c));
|
||||
}
|
||||
if (args.get(0) instanceof ListValue)
|
||||
{
|
||||
if (args.size() == 2)
|
||||
{
|
||||
Value dataValue = NBTSerializableValue.fromValue( args.get(1));
|
||||
if (dataValue instanceof NBTSerializableValue)
|
||||
{
|
||||
data = ((NBTSerializableValue) dataValue).getCompoundTag();
|
||||
}
|
||||
}
|
||||
args = ((ListValue) args.get(0)).getItems();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((args.size() & 1) == 1)
|
||||
{
|
||||
Value dataValue = NBTSerializableValue.fromValue( args.get(args.size()-1));
|
||||
if (dataValue instanceof NBTSerializableValue)
|
||||
{
|
||||
data = ((NBTSerializableValue) dataValue).getCompoundTag();
|
||||
}
|
||||
}
|
||||
}
|
||||
StateManager<Block, BlockState> states = sourceBlockState.getBlock().getStateManager();
|
||||
for (int i = 0; i < args.size()-1; i += 2)
|
||||
{
|
||||
String paramString = args.get(i).getString();
|
||||
Property<?> property = states.getProperty(paramString);
|
||||
if (property == null)
|
||||
throw new InternalExpressionException("Property " + paramString + " doesn't apply to " + sourceLocator.block.getString());
|
||||
String paramValue = lv.get(i + 1).evalValue(c).getString();
|
||||
String paramValue = args.get(i + 1).getString();
|
||||
sourceBlockState = setProperty(property, paramString, paramValue, sourceBlockState);
|
||||
}
|
||||
}
|
||||
|
||||
CompoundTag data = sourceLocator.block.getData();
|
||||
if (data == null) data = sourceLocator.block.getData();
|
||||
CompoundTag finalData = data;
|
||||
|
||||
if (sourceBlockState == targetBlockState && data == null)
|
||||
return (c_, t_) -> Value.FALSE;
|
||||
@@ -783,12 +842,12 @@ public class CarpetExpression
|
||||
{
|
||||
Clearable.clear(world.getBlockEntity(targetPos));
|
||||
world.setBlockState(targetPos, finalSourceBlockState, 2);
|
||||
if (data != null)
|
||||
if (finalData != null)
|
||||
{
|
||||
BlockEntity be = world.getBlockEntity(targetPos);
|
||||
if (be != null)
|
||||
{
|
||||
CompoundTag destTag = data.copy();
|
||||
CompoundTag destTag = finalData.copy();
|
||||
destTag.putInt("x", targetPos.getX());
|
||||
destTag.putInt("y", targetPos.getY());
|
||||
destTag.putInt("z", targetPos.getZ());
|
||||
@@ -897,7 +956,7 @@ public class CarpetExpression
|
||||
Tag outtag = tool.getTag();
|
||||
if (outtag == null)
|
||||
return LazyValue.TRUE;
|
||||
Value ret = new NBTSerializableValue(outtag);
|
||||
Value ret = new NBTSerializableValue(() -> outtag);
|
||||
return (_c, _t) -> ret;
|
||||
|
||||
});
|
||||
@@ -1096,6 +1155,9 @@ public class CarpetExpression
|
||||
BlockArgument locator = BlockArgument.findIn(cc, lv, 0);
|
||||
|
||||
ServerWorld world = cc.s.getWorld();
|
||||
|
||||
BooYah(world.getChunkManager().getChunkGenerator());
|
||||
|
||||
BlockPos pos = locator.block.getPos();
|
||||
StructureFeature<?> structure = null;
|
||||
boolean needSize = false;
|
||||
@@ -1385,13 +1447,14 @@ public class CarpetExpression
|
||||
});
|
||||
|
||||
this.expr.addLazyFunction("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.s.getMinecraftServer().getScoreboard();
|
||||
String objectiveName = lv.get(0).evalValue(c).getString();
|
||||
ScoreboardObjective objective = scoreboard.getObjective(objectiveName);
|
||||
if (objective == null)
|
||||
return LazyValue.FALSE;
|
||||
if (lv.size() == 0)
|
||||
if (lv.size() == 1)
|
||||
{
|
||||
scoreboard.removeObjective(objective);
|
||||
return LazyValue.TRUE;
|
||||
@@ -1472,6 +1535,120 @@ public class CarpetExpression
|
||||
return (_c, _t) -> res;
|
||||
});
|
||||
|
||||
this.expr.addLazyFunction("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).evalValue(c).getString();
|
||||
RecipeType type = RecipeType.CRAFTING;
|
||||
if (lv.size() > 1)
|
||||
{
|
||||
String recipeType = lv.get(1).evalValue(c).getString();
|
||||
try
|
||||
{
|
||||
type = Registry.RECIPE_TYPE.get(new Identifier(recipeType));
|
||||
}
|
||||
catch (InvalidIdentifierException ignored)
|
||||
{
|
||||
throw new InternalExpressionException("Unknown crafting category: " + recipeType);
|
||||
}
|
||||
}
|
||||
List<Recipe<?>> recipes;
|
||||
try
|
||||
{
|
||||
recipes = ((RecipeManagerInterface) cc.s.getMinecraftServer().getRecipeManager()).getAllMatching(type, new Identifier(recipeName));
|
||||
}
|
||||
catch (InvalidIdentifierException ignored)
|
||||
{
|
||||
return LazyValue.NULL;
|
||||
}
|
||||
if (recipes.isEmpty())
|
||||
return LazyValue.NULL;
|
||||
List<Value> recipesOutput = new ArrayList<>();
|
||||
for (Recipe<?> recipe: recipes)
|
||||
{
|
||||
ItemStack result = recipe.getOutput();
|
||||
List<Value> ingredientValue = new ArrayList<>();
|
||||
recipe.getPreviewInputs().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(ListValue::fromItemStack).forEach(alternatives::add));
|
||||
ingredientValue.add(ListValue.wrap(alternatives));
|
||||
}
|
||||
}
|
||||
);
|
||||
Value recipeSpec;
|
||||
if (recipe instanceof ShapedRecipe)
|
||||
{
|
||||
recipeSpec = ListValue.of(
|
||||
new StringValue("shaped"),
|
||||
new NumericValue(((ShapedRecipe) recipe).getWidth()),
|
||||
new NumericValue(((ShapedRecipe) recipe).getHeight())
|
||||
);
|
||||
}
|
||||
else if (recipe instanceof ShapelessRecipe)
|
||||
{
|
||||
recipeSpec = ListValue.of(new StringValue("shapeless"));
|
||||
}
|
||||
else if (recipe instanceof AbstractCookingRecipe)
|
||||
{
|
||||
recipeSpec = ListValue.of(
|
||||
new StringValue("smelting"),
|
||||
new NumericValue(((AbstractCookingRecipe) recipe).getCookTime()),
|
||||
new NumericValue(((AbstractCookingRecipe) recipe).getExperience())
|
||||
);
|
||||
}
|
||||
else if (recipe instanceof CuttingRecipe)
|
||||
{
|
||||
recipeSpec = ListValue.of(new StringValue("cutting"));
|
||||
}
|
||||
else if (recipe instanceof SpecialCraftingRecipe)
|
||||
{
|
||||
recipeSpec = ListValue.of(new StringValue("special"));
|
||||
}
|
||||
else
|
||||
{
|
||||
recipeSpec = ListValue.of(new StringValue("custom"));
|
||||
}
|
||||
|
||||
recipesOutput.add(ListValue.of(ListValue.fromItemStack(result), ListValue.wrap(ingredientValue), recipeSpec));
|
||||
}
|
||||
Value ret = ListValue.wrap(recipesOutput);
|
||||
return (_c, _t) -> ret;
|
||||
});
|
||||
|
||||
this.expr.addLazyFunction("crafting_remaining_item", 1, (c, t, lv) ->
|
||||
{
|
||||
String itemStr = lv.get(0).evalValue(c).getString();
|
||||
Item item;
|
||||
try
|
||||
{
|
||||
Identifier id = new Identifier(itemStr);
|
||||
item = Registry.ITEM.get(id);
|
||||
if (item == Items.AIR && !id.getPath().equalsIgnoreCase("air"))
|
||||
throw new InvalidIdentifierException("boo");
|
||||
}
|
||||
catch (InvalidIdentifierException ignored)
|
||||
{
|
||||
throw new InternalExpressionException("Incorrect item: "+itemStr);
|
||||
}
|
||||
if (!item.hasRecipeRemainder()) return LazyValue.NULL;
|
||||
Value ret = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.ITEM.getId(item.getRecipeRemainder())));
|
||||
return (_c, _t ) -> ret;
|
||||
});
|
||||
|
||||
|
||||
this.expr.addLazyFunction("inventory_size", -1, (c, t, lv) ->
|
||||
{
|
||||
CarpetContext cc = (CarpetContext) c;
|
||||
@@ -1825,11 +2002,9 @@ public class CarpetExpression
|
||||
Value nbt = lv.get(position.offset).evalValue(c);
|
||||
NBTSerializableValue v = (nbt instanceof NBTSerializableValue) ? (NBTSerializableValue) nbt
|
||||
: NBTSerializableValue.parseString(nbt.getString());
|
||||
if (v != null)
|
||||
{
|
||||
hasTag = true;
|
||||
tag = v.getCompoundTag();
|
||||
}
|
||||
hasTag = true;
|
||||
tag = v.getCompoundTag();
|
||||
|
||||
}
|
||||
tag.putString("id", entityId.toString());
|
||||
Vec3d vec3d = position.vec;
|
||||
@@ -2097,21 +2272,28 @@ public class CarpetExpression
|
||||
return (c_, t_) -> new NumericValue(finalSCount);
|
||||
});
|
||||
|
||||
this.expr.addLazyFunction("volume", 7, (c, t, lv) ->
|
||||
this.expr.addLazyFunction("volume", -1, (c, t, lv) ->
|
||||
{
|
||||
int xi = (int) NumericValue.asNumber(lv.get(0).evalValue(c)).getLong();
|
||||
int yi = (int) NumericValue.asNumber(lv.get(1).evalValue(c)).getLong();
|
||||
int zi = (int) NumericValue.asNumber(lv.get(2).evalValue(c)).getLong();
|
||||
int xj = (int) NumericValue.asNumber(lv.get(3).evalValue(c)).getLong();
|
||||
int yj = (int) NumericValue.asNumber(lv.get(4).evalValue(c)).getLong();
|
||||
int zj = (int) NumericValue.asNumber(lv.get(5).evalValue(c)).getLong();
|
||||
int minx = min(xi, xj);
|
||||
int miny = min(yi, yj);
|
||||
int minz = min(zi, zj);
|
||||
int maxx = max(xi, xj);
|
||||
int maxy = max(yi, yj);
|
||||
int maxz = max(zi, zj);
|
||||
LazyValue expr = lv.get(6);
|
||||
CarpetContext cc = (CarpetContext)c;
|
||||
|
||||
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();
|
||||
|
||||
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 = lv.get(pos2Locator.offset);
|
||||
|
||||
//saving outer scope
|
||||
LazyValue _x = c.getVariable("_x");
|
||||
@@ -2181,57 +2363,63 @@ public class CarpetExpression
|
||||
|
||||
this.expr.addLazyFunction("rect", -1, (c, t, lv)->
|
||||
{
|
||||
if (lv.size() != 3 && lv.size() != 6 && lv.size() != 9)
|
||||
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();
|
||||
cx = cpos.getX();
|
||||
cy = cpos.getY();
|
||||
cz = cpos.getZ();
|
||||
if (lv.size() > cposLocator.offset)
|
||||
{
|
||||
throw new InternalExpressionException("Rectangular region should be specified with 3, 6, or 9 coordinates");
|
||||
}
|
||||
int cx;
|
||||
int cy;
|
||||
int cz;
|
||||
int sminx;
|
||||
int sminy;
|
||||
int sminz;
|
||||
int smaxx;
|
||||
int smaxy;
|
||||
int smaxz;
|
||||
try
|
||||
{
|
||||
cx = (int)((NumericValue) lv.get(0).evalValue(c)).getLong();
|
||||
cy = (int)((NumericValue) lv.get(1).evalValue(c)).getLong();
|
||||
cz = (int)((NumericValue) lv.get(2).evalValue(c)).getLong();
|
||||
if (lv.size()==3) // only done this way because of stupid Java lambda final reqs
|
||||
Vector3Argument diffLocator = Vector3Argument.findIn(cc, lv, cposLocator.offset);
|
||||
if (diffLocator.fromBlock)
|
||||
{
|
||||
sminx = 1;
|
||||
sminy = 1;
|
||||
sminz = 1;
|
||||
smaxx = 1;
|
||||
smaxy = 1;
|
||||
smaxz = 1;
|
||||
sminx = MathHelper.floor(abs(diffLocator.vec.x - cx));
|
||||
sminy = MathHelper.floor(abs(diffLocator.vec.y - cx));
|
||||
sminz = MathHelper.floor(abs(diffLocator.vec.z - cx));
|
||||
}
|
||||
else if (lv.size()==6)
|
||||
else
|
||||
{
|
||||
sminx = MathHelper.floor(abs(diffLocator.vec.x));
|
||||
sminy = MathHelper.floor(abs(diffLocator.vec.y));
|
||||
sminz = MathHelper.floor(abs(diffLocator.vec.z));
|
||||
}
|
||||
if (lv.size() > diffLocator.offset)
|
||||
{
|
||||
Vector3Argument posDiff = Vector3Argument.findIn(cc, lv, diffLocator.offset);
|
||||
if (posDiff.fromBlock)
|
||||
{
|
||||
smaxx = MathHelper.floor(abs(posDiff.vec.x - cx));
|
||||
smaxy = MathHelper.floor(abs(posDiff.vec.y - cx));
|
||||
smaxz = MathHelper.floor(abs(posDiff.vec.z - cx));
|
||||
}
|
||||
else
|
||||
{
|
||||
smaxx = MathHelper.floor(abs(posDiff.vec.x));
|
||||
smaxy = MathHelper.floor(abs(posDiff.vec.y));
|
||||
smaxz = MathHelper.floor(abs(posDiff.vec.z));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sminx = (int) ((NumericValue) lv.get(3).evalValue(c)).getLong();
|
||||
sminy = (int) ((NumericValue) lv.get(4).evalValue(c)).getLong();
|
||||
sminz = (int) ((NumericValue) lv.get(5).evalValue(c)).getLong();
|
||||
smaxx = sminx;
|
||||
smaxy = sminy;
|
||||
smaxz = sminz;
|
||||
}
|
||||
else // size == 9
|
||||
{
|
||||
sminx = (int) ((NumericValue) lv.get(3).evalValue(c)).getLong();
|
||||
sminy = (int) ((NumericValue) lv.get(4).evalValue(c)).getLong();
|
||||
sminz = (int) ((NumericValue) lv.get(5).evalValue(c)).getLong();
|
||||
smaxx = (int)((NumericValue) lv.get(6).evalValue(c)).getLong();
|
||||
smaxy = (int)((NumericValue) lv.get(7).evalValue(c)).getLong();
|
||||
smaxz = (int)((NumericValue) lv.get(8).evalValue(c)).getLong();
|
||||
}
|
||||
}
|
||||
catch (ClassCastException exc)
|
||||
else
|
||||
{
|
||||
throw new InternalExpressionException("Attempted to pass a non-number to rect");
|
||||
sminx = 1;
|
||||
sminy = 1;
|
||||
sminz = 1;
|
||||
smaxx = 1;
|
||||
smaxy = 1;
|
||||
smaxz = 1;
|
||||
}
|
||||
CarpetContext cc = (CarpetContext)c;
|
||||
|
||||
return (c_, t_) -> new LazyListValue()
|
||||
{
|
||||
final int minx = cx-sminx;
|
||||
@@ -2240,6 +2428,7 @@ public class CarpetExpression
|
||||
final int maxx = cx+smaxx;
|
||||
final int maxy = cy+smaxy;
|
||||
final int maxz = cz+smaxz;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
@@ -2299,10 +2488,9 @@ public class CarpetExpression
|
||||
this.expr.addLazyFunction("diamond", -1, (c, t, lv)->
|
||||
{
|
||||
CarpetContext cc = (CarpetContext)c;
|
||||
if (lv.size() != 3 && lv.size() != 4 && lv.size() != 5)
|
||||
{
|
||||
throw new InternalExpressionException("'diamond' region should be specified with 3 to 5 coordinates");
|
||||
}
|
||||
|
||||
BlockArgument cposLocator=BlockArgument.findIn((CarpetContext)c,lv,0);
|
||||
BlockPos cpos = cposLocator.block.getPos();
|
||||
|
||||
int cx;
|
||||
int cy;
|
||||
@@ -2311,10 +2499,11 @@ public class CarpetExpression
|
||||
int height;
|
||||
try
|
||||
{
|
||||
cx = (int)((NumericValue) lv.get(0).evalValue(c)).getLong();
|
||||
cy = (int)((NumericValue) lv.get(1).evalValue(c)).getLong();
|
||||
cz = (int)((NumericValue) lv.get(2).evalValue(c)).getLong();
|
||||
if (lv.size()==3)
|
||||
cx = cpos.getX();
|
||||
cy = cpos.getY();
|
||||
cz = cpos.getZ();
|
||||
|
||||
if (lv.size()==cposLocator.offset)
|
||||
{
|
||||
Value retval = ListValue.of(
|
||||
BlockValue.fromCoords(cc, cx, cy-1, cz),
|
||||
@@ -2327,20 +2516,22 @@ public class CarpetExpression
|
||||
);
|
||||
return (_c, _t ) -> retval;
|
||||
}
|
||||
else if (lv.size()==4)
|
||||
else if (lv.size()==1+cposLocator.offset)
|
||||
{
|
||||
width = (int) ((NumericValue) lv.get(3).evalValue(c)).getLong();
|
||||
width = (int) ((NumericValue) lv.get(cposLocator.offset).evalValue(c)).getLong();
|
||||
height = 0;
|
||||
}
|
||||
else // size == 5
|
||||
else if(lv.size()==2+cposLocator.offset)
|
||||
{
|
||||
width = (int) ((NumericValue) lv.get(3).evalValue(c)).getLong();
|
||||
height = (int) ((NumericValue) lv.get(4).evalValue(c)).getLong();
|
||||
width = (int) ((NumericValue) lv.get(cposLocator.offset).evalValue(c)).getLong();
|
||||
height = (int) ((NumericValue) lv.get(cposLocator.offset+1).evalValue(c)).getLong();
|
||||
} else{
|
||||
throw new InternalExpressionException("Incorrect number of arguments for 'diamond'");
|
||||
}
|
||||
}
|
||||
catch (ClassCastException exc)
|
||||
{
|
||||
throw new InternalExpressionException("Attempted to pass a non-number to diamond");
|
||||
throw new InternalExpressionException("Attempted to pass a non-number to 'diamond'");
|
||||
}
|
||||
if (height == 0)
|
||||
{
|
||||
@@ -2480,7 +2671,7 @@ public class CarpetExpression
|
||||
public static String recognizeResource(Value value)
|
||||
{
|
||||
String origfile = value.getString();
|
||||
String file = origfile.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9/]", "");
|
||||
String file = origfile.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9\\-+_/]", "");
|
||||
file = Arrays.stream(file.split("/+")).filter(s -> !s.isEmpty()).collect(Collectors.joining("/"));
|
||||
if (file.isEmpty())
|
||||
{
|
||||
@@ -2756,12 +2947,7 @@ public class CarpetExpression
|
||||
});
|
||||
|
||||
this.expr.addLazyFunction("nbt", 1, (c, t, lv) -> {
|
||||
Value v = lv.get(0).evalValue(c);
|
||||
if (v instanceof NBTSerializableValue)
|
||||
return (cc, tt) -> v;
|
||||
Value ret = NBTSerializableValue.parseString(v.getString());
|
||||
if (ret == null)
|
||||
return LazyValue.NULL;
|
||||
Value ret = NBTSerializableValue.fromValue(lv.get(0).evalValue(c));
|
||||
return (cc, tt) -> ret;
|
||||
});
|
||||
|
||||
@@ -2772,11 +2958,50 @@ public class CarpetExpression
|
||||
return (cc, tt) -> ret;
|
||||
});
|
||||
|
||||
this.expr.addLazyFunction("parse_nbt", 1, (c, t, lv) -> {
|
||||
Value v = lv.get(0).evalValue(c);
|
||||
if (v instanceof NBTSerializableValue)
|
||||
{
|
||||
Value parsed = ((NBTSerializableValue) v).toValue();
|
||||
return (cc, tt) -> parsed;
|
||||
}
|
||||
NBTSerializableValue ret = NBTSerializableValue.parseString(v.getString());
|
||||
if (ret == null)
|
||||
return LazyValue.NULL;
|
||||
Value parsed = ret.toValue();
|
||||
return (cc, tt) -> parsed;
|
||||
});
|
||||
|
||||
this.expr.addLazyFunction("encode_nbt", -1, (c, t, lv) -> {
|
||||
int argSize = lv.size();
|
||||
if (argSize==0 || argSize > 2) throw new InternalExpressionException("'encode_nbt' requires 1 or 2 parameters");
|
||||
Value v = lv.get(0).evalValue(c);
|
||||
boolean force = (argSize > 1) && lv.get(1).evalValue(c).getBoolean();
|
||||
Tag tag;
|
||||
try
|
||||
{
|
||||
tag = v.toTag(force);
|
||||
}
|
||||
catch (NBTSerializableValue.IncompatibleTypeException ignored)
|
||||
{
|
||||
throw new InternalExpressionException("cannot reliably encode to a tag the value of '"+ignored.val.getPrettyString()+"'");
|
||||
}
|
||||
Value tagValue = new NBTSerializableValue(tag);
|
||||
return (cc, tt) -> tagValue;
|
||||
});
|
||||
|
||||
//"overridden" native call that prints to stderr
|
||||
this.expr.addLazyFunction("print", 1, (c, t, lv) ->
|
||||
this.expr.addLazyFunction("print", -1, (c, t, lv) ->
|
||||
{
|
||||
if (lv.size() == 0 || lv.size() > 2) throw new InternalExpressionException("'print' takes one or two arguments");
|
||||
ServerCommandSource s = ((CarpetContext)c).s;
|
||||
Value res = lv.get(0).evalValue(c);
|
||||
if (lv.size() == 2)
|
||||
{
|
||||
ServerPlayerEntity player = EntityValue.getPlayerByValue(s.getMinecraftServer(), res);
|
||||
s = player.getCommandSource();
|
||||
res = lv.get(1).evalValue(c);
|
||||
}
|
||||
if (res instanceof FormattedTextValue)
|
||||
{
|
||||
s.sendFeedback(((FormattedTextValue) res).getText(), false);
|
||||
@@ -2792,7 +3017,8 @@ public class CarpetExpression
|
||||
Messenger.m(s, "w " + res.getString());
|
||||
}
|
||||
}
|
||||
return (_c, _t) -> res; // pass through for variables
|
||||
Value finalRes = res;
|
||||
return (_c, _t) -> finalRes; // pass through for variables
|
||||
});
|
||||
|
||||
this.expr.addLazyFunction("format", -1, (c, t, lv) -> {
|
||||
@@ -2862,9 +3088,14 @@ public class CarpetExpression
|
||||
BlockPos target = ((CarpetContext)c).origin;
|
||||
Vec3d posf = new Vec3d((double)target.getX()+0.5D,(double)target.getY(),(double)target.getZ()+0.5D);
|
||||
ServerCommandSource s = ((CarpetContext)c).s;
|
||||
Value retval = new NumericValue(s.getMinecraftServer().getCommandManager().execute(
|
||||
s.withPosition(posf).withSilent().withLevel(CarpetSettings.runPermissionLevel), lv.get(0).evalValue(c).getString()));
|
||||
return (c_, t_) -> retval;
|
||||
try
|
||||
{
|
||||
Value retval = new NumericValue(s.getMinecraftServer().getCommandManager().execute(
|
||||
s.withPosition(posf).withSilent().withLevel(CarpetSettings.runPermissionLevel), lv.get(0).evalValue(c).getString()));
|
||||
return (c_, t_) -> retval;
|
||||
}
|
||||
catch (Exception ignored) {}
|
||||
return LazyValue.NULL;
|
||||
});
|
||||
|
||||
this.expr.addLazyFunction("save", 0, (c, t, lv) -> {
|
||||
@@ -2945,7 +3176,7 @@ public class CarpetExpression
|
||||
|
||||
this.expr.addLazyFunction("seed", -1, (c, t, lv) -> {
|
||||
ServerCommandSource s = ((CarpetContext)c).s;
|
||||
Value ret = new NumericValue(s.getWorld().getSeed());
|
||||
Value ret = new StringValue(Long.toString(s.getWorld().getSeed()));
|
||||
return (cc, tt) -> ret;
|
||||
});
|
||||
|
||||
@@ -3013,10 +3244,12 @@ public class CarpetExpression
|
||||
default:
|
||||
throw new InternalExpressionException("Incorrect dimension string: "+dimString);
|
||||
}
|
||||
}
|
||||
((CarpetContext) c).s = innerSource;
|
||||
Value retval = lv.get(1).evalValue(c);
|
||||
((CarpetContext) c).s = outerSource;
|
||||
};
|
||||
if (innerSource.getWorld() == outerSource.getWorld()) return lv.get(1);
|
||||
Context newCtx = c.recreate();
|
||||
((CarpetContext) newCtx).s = innerSource;
|
||||
newCtx.variables = c.variables;
|
||||
Value retval = lv.get(1).evalValue(newCtx);
|
||||
return (cc, tt) -> retval;
|
||||
});
|
||||
|
||||
|
||||
@@ -18,8 +18,9 @@ public class Context
|
||||
public static final int SIGNATURE = 7;
|
||||
public static final int LOCALIZATION = 8;
|
||||
public static final int LVALUE = 9;
|
||||
public static final int MAPDEF = 10;
|
||||
|
||||
public final Map<String, LazyValue> variables = new HashMap<>();
|
||||
public Map<String, LazyValue> variables = new HashMap<>();
|
||||
|
||||
public final ScriptHost host;
|
||||
|
||||
|
||||
@@ -43,7 +43,9 @@ import org.apache.commons.lang3.text.WordUtils;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.IllegalFormatException;
|
||||
import java.util.Iterator;
|
||||
@@ -490,6 +492,11 @@ public class Expression
|
||||
//assigns const procedure to the lhs, returning its previous value
|
||||
addLazyBinaryOperatorWithDelegation("->", precedence.get("def->"), false, (c, type, e, t, lv1, lv2) ->
|
||||
{
|
||||
if (type == Context.MAPDEF)
|
||||
{
|
||||
Value result = ListValue.of(lv1.evalValue(c), lv2.evalValue(c));
|
||||
return (cc, tt) -> result;
|
||||
}
|
||||
Value v1 = lv1.evalValue(c, Context.SIGNATURE);
|
||||
if (!(v1 instanceof FunctionSignatureValue))
|
||||
throw new InternalExpressionException("'->' operator requires a function signature on the LHS");
|
||||
@@ -1333,11 +1340,18 @@ public class Expression
|
||||
return LazyListValue.range(from, to, step);
|
||||
});
|
||||
|
||||
addFunction("m", lv ->
|
||||
addLazyFunction("m", -1, (c, t, llv) ->
|
||||
{
|
||||
List<Value> lv = new ArrayList<>();
|
||||
for (LazyValue lazyParam : llv) {
|
||||
lv.add(lazyParam.evalValue(c, Context.MAPDEF)); // none type default by design
|
||||
}
|
||||
Value ret;
|
||||
if (lv.size() == 1 && lv.get(0) instanceof LazyListValue)
|
||||
return new MapValue(((LazyListValue) lv.get(0)).unroll());
|
||||
return new MapValue(lv);
|
||||
ret = new MapValue(((LazyListValue) lv.get(0)).unroll());
|
||||
else
|
||||
ret = new MapValue(lv);
|
||||
return (cc, tt) -> ret;
|
||||
});
|
||||
|
||||
addUnaryFunction("keys", v -> {
|
||||
@@ -1449,20 +1463,6 @@ public class Expression
|
||||
return (cc, tt) -> ret;
|
||||
});
|
||||
|
||||
//Deprecated, use "get" instead, or . operator
|
||||
addBinaryFunction("element", (v1, v2) ->
|
||||
{
|
||||
if (!(v1 instanceof ListValue))
|
||||
throw new InternalExpressionException("First argument of 'get' should be a list");
|
||||
List<Value> items = ((ListValue)v1).getItems();
|
||||
long index = NumericValue.asNumber(v2).getLong();
|
||||
int numitems = items.size();
|
||||
long range = abs(index)/numitems;
|
||||
index += (range+2)*numitems;
|
||||
index = index % numitems;
|
||||
return items.get((int)index);
|
||||
});
|
||||
|
||||
addLazyFunction("put", -1, (c, t, lv) ->
|
||||
{
|
||||
if(lv.size()<2)
|
||||
@@ -1790,6 +1790,66 @@ public class Expression
|
||||
return (cc, tt) -> time;
|
||||
});
|
||||
|
||||
addLazyFunction("unix_time", 0, (c, t, lv) ->
|
||||
{
|
||||
Value time = new NumericValue(System.currentTimeMillis());
|
||||
return (cc, tt) -> time;
|
||||
});
|
||||
|
||||
addFunction("convert_date", lv ->
|
||||
{
|
||||
int argsize = lv.size();
|
||||
if (lv.size() == 0) throw new InternalExpressionException("'convert_date' requires at least one parameter");
|
||||
Value value = lv.get(0);
|
||||
if (argsize == 1 && !(value instanceof ListValue))
|
||||
{
|
||||
Calendar cal = new GregorianCalendar(Locale.ROOT);
|
||||
cal.setTimeInMillis(NumericValue.asNumber(value, "timestamp").getLong());
|
||||
int weekday = cal.get(Calendar.DAY_OF_WEEK)-1;
|
||||
if (weekday == 0) weekday = 7;
|
||||
Value retVal = ListValue.ofNums(
|
||||
cal.get(Calendar.YEAR),
|
||||
cal.get(Calendar.MONTH)+1,
|
||||
cal.get(Calendar.DAY_OF_MONTH),
|
||||
cal.get(Calendar.HOUR_OF_DAY),
|
||||
cal.get(Calendar.MINUTE),
|
||||
cal.get(Calendar.SECOND),
|
||||
weekday,
|
||||
cal.get(Calendar.DAY_OF_YEAR),
|
||||
cal.get(Calendar.WEEK_OF_YEAR)
|
||||
);
|
||||
return retVal;
|
||||
}
|
||||
else if(value instanceof ListValue)
|
||||
{
|
||||
lv = ((ListValue) value).getItems();
|
||||
argsize = lv.size();
|
||||
}
|
||||
Calendar cal = new GregorianCalendar(0, 0, 0, 0, 0, 0);
|
||||
|
||||
if (argsize == 3)
|
||||
{
|
||||
cal.set(
|
||||
NumericValue.asNumber(lv.get(0)).getInt(),
|
||||
NumericValue.asNumber(lv.get(1)).getInt()-1,
|
||||
NumericValue.asNumber(lv.get(2)).getInt()
|
||||
);
|
||||
}
|
||||
else if (argsize == 6)
|
||||
{
|
||||
cal.set(
|
||||
NumericValue.asNumber(lv.get(0)).getInt(),
|
||||
NumericValue.asNumber(lv.get(1)).getInt()-1,
|
||||
NumericValue.asNumber(lv.get(2)).getInt(),
|
||||
NumericValue.asNumber(lv.get(3)).getInt(),
|
||||
NumericValue.asNumber(lv.get(4)).getInt(),
|
||||
NumericValue.asNumber(lv.get(5)).getInt()
|
||||
);
|
||||
}
|
||||
else throw new InternalExpressionException("Date conversion requires 3 arguments for Dates or 6 arguments, for time");
|
||||
return new NumericValue(cal.getTimeInMillis());
|
||||
});
|
||||
|
||||
addLazyFunction("profile_expr", 1, (c, t, lv) ->
|
||||
{
|
||||
LazyValue lazy = lv.get(0);
|
||||
@@ -2000,7 +2060,7 @@ public class Expression
|
||||
|
||||
Tokenizer tokenizer = new Tokenizer(c, this, expression, allowComments, allowNewlineSubstitutions);
|
||||
// stripping lousy but acceptable semicolons
|
||||
List<Tokenizer.Token> cleanedTokens = tokenizer.fixSemicolons();
|
||||
List<Tokenizer.Token> cleanedTokens = tokenizer.postProcess();
|
||||
|
||||
Tokenizer.Token lastFunction = null;
|
||||
Tokenizer.Token previousToken = null;
|
||||
|
||||
@@ -43,7 +43,7 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
||||
this.newLinesMarkers = allowNewLineMakers;
|
||||
}
|
||||
|
||||
public List<Token> fixSemicolons()
|
||||
public List<Token> postProcess()
|
||||
{
|
||||
Iterable<Token> iterable = () -> this;
|
||||
List<Token> originalTokens = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList());
|
||||
@@ -52,6 +52,9 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
||||
while (originalTokens.size() > 0)
|
||||
{
|
||||
Token current = originalTokens.remove(originalTokens.size()-1);
|
||||
if (current.type == Token.TokenType.MARKER && current.surface.startsWith("//"))
|
||||
continue;
|
||||
// skipping comments
|
||||
if (!isSemicolon(current)
|
||||
|| (last != null && last.type != Token.TokenType.CLOSE_PAREN && last.type != Token.TokenType.COMMA && !isSemicolon(last)))
|
||||
{
|
||||
@@ -60,9 +63,27 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
||||
current.surface = ";";
|
||||
current.type = Token.TokenType.OPERATOR;
|
||||
}
|
||||
if (current.type == Token.TokenType.MARKER)
|
||||
{
|
||||
// dealing with tokens in reversed order
|
||||
if ("{".equals(current.surface))
|
||||
{
|
||||
cleanedTokens.add(current.morphedInto(Token.TokenType.OPEN_PAREN, "("));
|
||||
current.morph(Token.TokenType.FUNCTION, "m");
|
||||
}
|
||||
else if ("[".equals(current.surface))
|
||||
{
|
||||
cleanedTokens.add(current.morphedInto(Token.TokenType.OPEN_PAREN, "("));
|
||||
current.morph(Token.TokenType.FUNCTION, "l");
|
||||
}
|
||||
else if ("}".equals(current.surface) || "]".equals(current.surface))
|
||||
{
|
||||
current.morph(Token.TokenType.CLOSE_PAREN, ")");
|
||||
}
|
||||
}
|
||||
cleanedTokens.add(current);
|
||||
}
|
||||
if (current.type != Token.TokenType.MARKER)
|
||||
if (!(current.type == Token.TokenType.MARKER && current.surface.equals("$")))
|
||||
last = current;
|
||||
}
|
||||
Collections.reverse(cleanedTokens);
|
||||
@@ -242,7 +263,8 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
||||
}
|
||||
token.type = ch == '(' ? Token.TokenType.FUNCTION : Token.TokenType.VARIABLE;
|
||||
}
|
||||
else if (ch == '(' || ch == ')' || ch == ',')
|
||||
else if (ch == '(' || ch == ')' || ch == ',' ||
|
||||
ch == '{' || ch == '}' || ch == '[' || ch == ']')
|
||||
{
|
||||
if (ch == '(')
|
||||
{
|
||||
@@ -252,17 +274,21 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
||||
{
|
||||
token.type = Token.TokenType.CLOSE_PAREN;
|
||||
}
|
||||
else
|
||||
else if (ch == ',')
|
||||
{
|
||||
token.type = Token.TokenType.COMMA;
|
||||
}
|
||||
else
|
||||
{
|
||||
token.type = Token.TokenType.MARKER;
|
||||
}
|
||||
token.append(ch);
|
||||
pos++;
|
||||
linepos++;
|
||||
|
||||
if (expression != null && context != null && previousToken != null &&
|
||||
previousToken.type == Token.TokenType.OPERATOR &&
|
||||
(ch == ')' || ch == ',') &&
|
||||
(ch == ')' || ch == ',' || ch == ']' || ch == '}') &&
|
||||
!previousToken.surface.equalsIgnoreCase(";")
|
||||
)
|
||||
throw new ExpressionException(context, this.expression, previousToken,
|
||||
@@ -326,7 +352,9 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
||||
}
|
||||
|
||||
if (previousToken == null || previousToken.type == Token.TokenType.OPERATOR
|
||||
|| previousToken.type == Token.TokenType.OPEN_PAREN || previousToken.type == Token.TokenType.COMMA)
|
||||
|| previousToken.type == Token.TokenType.OPEN_PAREN || previousToken.type == Token.TokenType.COMMA
|
||||
|| (previousToken.type == Token.TokenType.MARKER && ( previousToken.surface.equals("{") || previousToken.surface.equals("[") ) )
|
||||
)
|
||||
{
|
||||
token.surface += "u";
|
||||
token.type = Token.TokenType.UNARY_OPERATOR;
|
||||
@@ -376,6 +404,22 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
||||
public int pos;
|
||||
public int linepos;
|
||||
public int lineno;
|
||||
public Token morphedInto(TokenType newType, String newSurface)
|
||||
{
|
||||
Token created = new Token();
|
||||
created.surface = newSurface;
|
||||
created.type = newType;
|
||||
created.pos = pos;
|
||||
created.linepos = linepos;
|
||||
created.lineno= lineno;
|
||||
return created;
|
||||
}
|
||||
|
||||
public void morph(TokenType type, String s)
|
||||
{
|
||||
this.type = type;
|
||||
this.surface = s;
|
||||
}
|
||||
|
||||
public void append(char c)
|
||||
{
|
||||
|
||||
@@ -39,16 +39,13 @@ public class ShapesRenderer
|
||||
{
|
||||
this.client = minecraftClient;
|
||||
shapes = new HashMap<>();
|
||||
shapes.put(DimensionType.OVERWORLD, new Long2ObjectOpenHashMap<>());
|
||||
shapes.put(DimensionType.THE_NETHER, new Long2ObjectOpenHashMap<>());
|
||||
shapes.put(DimensionType.THE_END, new Long2ObjectOpenHashMap<>());
|
||||
}
|
||||
|
||||
public void render(Camera camera, float partialTick)
|
||||
{
|
||||
IWorld iWorld = this.client.world;
|
||||
DimensionType dimensionType = iWorld.getDimension().getType();
|
||||
if (shapes.get(dimensionType).isEmpty()) return;
|
||||
if (shapes.get(dimensionType) == null || shapes.get(dimensionType).isEmpty()) return;
|
||||
long currentTime = client.world.getTime();
|
||||
RenderSystem.disableTexture();
|
||||
RenderSystem.enableDepthTest();
|
||||
@@ -59,8 +56,7 @@ public class ShapesRenderer
|
||||
//RenderSystem.shadeModel(7425);
|
||||
RenderSystem.shadeModel(GL11.GL_FLAT);
|
||||
RenderSystem.enableAlphaTest();
|
||||
RenderSystem.defaultAlphaFunc();
|
||||
//RenderSystem.alphaFunc(GL11.GL_GREATER, 0.005F);
|
||||
RenderSystem.alphaFunc(GL11.GL_GREATER, 0.003f);
|
||||
RenderSystem.disableCull();
|
||||
RenderSystem.disableLighting();
|
||||
RenderSystem.depthMask(false);
|
||||
@@ -131,7 +127,7 @@ public class ShapesRenderer
|
||||
long key = rshape.key();
|
||||
synchronized (shapes)
|
||||
{
|
||||
RenderedShape<?> existing = shapes.get(dim).get(key);
|
||||
RenderedShape<?> existing = shapes.computeIfAbsent(dim, d -> new Long2ObjectOpenHashMap<>()).get(key);
|
||||
if (existing != null)
|
||||
{ // promoting previous shape
|
||||
existing.expiryTick = rshape.expiryTick;
|
||||
|
||||
@@ -12,7 +12,10 @@ import net.minecraft.block.Blocks;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.state.property.Property;
|
||||
import net.minecraft.util.GlobalPos;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
@@ -24,8 +27,10 @@ import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.WorldChunk;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -180,6 +185,33 @@ public class BlockValue extends Value
|
||||
|
||||
public ServerWorld getWorld() { return world;}
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
|
||||
// follows falling block convertion
|
||||
CompoundTag tag = new CompoundTag();
|
||||
CompoundTag state = new CompoundTag();
|
||||
BlockState s = getBlockState();
|
||||
state.put("Name", StringTag.of(Registry.BLOCK.getId(s.getBlock()).toString()));
|
||||
Collection<Property<?>> properties = s.getProperties();
|
||||
if (!properties.isEmpty())
|
||||
{
|
||||
CompoundTag props = new CompoundTag();
|
||||
for (Property<?> p: properties)
|
||||
{
|
||||
props.put(p.getName(), StringTag.of(s.get(p).toString().toLowerCase(Locale.ROOT)));
|
||||
}
|
||||
state.put("Properties", props);
|
||||
}
|
||||
tag.put("BlockState", state);
|
||||
CompoundTag dataTag = getData();
|
||||
if (dataTag != null)
|
||||
{
|
||||
tag.put("TileEntityData", dataTag);
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
public enum SpecificDirection {
|
||||
UP("up",0.5, 0.0, 0.5, Direction.UP),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.fakes.EntityInterface;
|
||||
import carpet.fakes.ItemEntityInterface;
|
||||
import carpet.fakes.LivingEntityInterface;
|
||||
@@ -12,10 +11,10 @@ import carpet.script.CarpetContext;
|
||||
import carpet.script.EntityEventsGroup;
|
||||
import carpet.script.argument.Vector3Argument;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import carpet.utils.Messenger;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.entity.player.HungerManager;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.packet.s2c.play.EntityPassengersSetS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.EntityPositionS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket;
|
||||
@@ -61,6 +60,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
@@ -87,11 +87,11 @@ public class EntityValue extends Value
|
||||
EntitySelector entitySelector = selectorCache.get(selector);
|
||||
if (entitySelector != null)
|
||||
{
|
||||
return entitySelector.getEntities(source);
|
||||
return entitySelector.getEntities(source.withMaxLevel(4));
|
||||
}
|
||||
entitySelector = new EntitySelectorReader(new StringReader(selector), true).read();
|
||||
selectorCache.put(selector, entitySelector);
|
||||
return entitySelector.getEntities(source);
|
||||
return entitySelector.getEntities(source.withMaxLevel(4));
|
||||
}
|
||||
catch (CommandSyntaxException e)
|
||||
{
|
||||
@@ -289,6 +289,10 @@ public class EntityValue extends Value
|
||||
put("sneaking", (e, a) -> e.isSneaking()?Value.TRUE:Value.FALSE);
|
||||
put("sprinting", (e, a) -> e.isSprinting()?Value.TRUE:Value.FALSE);
|
||||
put("swimming", (e, a) -> e.isSwimming()?Value.TRUE:Value.FALSE);
|
||||
put("persistence", (e, a) -> {
|
||||
if (e instanceof MobEntity) return new NumericValue(((MobEntity) e).isPersistent());
|
||||
return Value.NULL;
|
||||
});
|
||||
put("hunger", (e, a) -> {
|
||||
if(e instanceof PlayerEntity) return new NumericValue(((PlayerEntity) e).getHungerManager().getFoodLevel());
|
||||
return Value.NULL;
|
||||
@@ -520,6 +524,10 @@ public class EntityValue extends Value
|
||||
{
|
||||
throw new InternalExpressionException("'modify' for '"+what+"' expects a value");
|
||||
}
|
||||
catch (IndexOutOfBoundsException ind)
|
||||
{
|
||||
throw new InternalExpressionException("Wrong number of arguments for `modify` option: "+what);
|
||||
}
|
||||
}
|
||||
|
||||
private static void updatePosition(Entity e, double x, double y, double z, float yaw, float pitch)
|
||||
@@ -715,9 +723,23 @@ public class EntityValue extends Value
|
||||
e.setCustomName(null);
|
||||
return;
|
||||
}
|
||||
e.setCustomNameVisible(true);
|
||||
boolean showName = false;
|
||||
if (v instanceof ListValue)
|
||||
{
|
||||
showName = ((ListValue) v).getItems().get(1).getBoolean();
|
||||
v = ((ListValue) v).getItems().get(0);
|
||||
}
|
||||
e.setCustomNameVisible(showName);
|
||||
e.setCustomName(new LiteralText(v.getString()));
|
||||
});
|
||||
|
||||
put("persistence", (e, v) ->
|
||||
{
|
||||
if (!(e instanceof MobEntity)) return;
|
||||
if (v == null) v = Value.TRUE;
|
||||
((MobEntityInterface)e).setPersistence(v.getBoolean());
|
||||
});
|
||||
|
||||
put("dismount", (e, v) -> e.stopRiding() );
|
||||
put("mount", (e, v) -> {
|
||||
if (v instanceof EntityValue)
|
||||
@@ -976,22 +998,37 @@ public class EntityValue extends Value
|
||||
if(e instanceof PlayerEntity) ((PlayerEntity) e).getHungerManager().setSaturationLevelClient((float)NumericValue.asNumber(v).getLong());
|
||||
});
|
||||
|
||||
// gamemode [check]
|
||||
// spectate [check]
|
||||
// "fire" [check]
|
||||
// "extinguish" [set fire ticks to 0]
|
||||
// "silent" [check]
|
||||
// "gravity" [check]
|
||||
// "invulnerable" [check]
|
||||
put("nbt", (e, v) -> {
|
||||
if (!(e instanceof PlayerEntity))
|
||||
{
|
||||
UUID uUID = e.getUuid();
|
||||
Value tagValue = NBTSerializableValue.fromValue(v);
|
||||
if (tagValue instanceof NBTSerializableValue)
|
||||
{
|
||||
e.fromTag(((NBTSerializableValue) tagValue).getCompoundTag());
|
||||
e.setUuid(uUID);
|
||||
}
|
||||
}
|
||||
});
|
||||
put("nbt_merge", (e, v) -> {
|
||||
if (!(e instanceof PlayerEntity))
|
||||
{
|
||||
UUID uUID = e.getUuid();
|
||||
Value tagValue = NBTSerializableValue.fromValue(v);
|
||||
if (tagValue instanceof NBTSerializableValue)
|
||||
{
|
||||
CompoundTag nbttagcompound = e.toTag((new CompoundTag()));
|
||||
nbttagcompound.copyFrom(((NBTSerializableValue) tagValue).getCompoundTag());
|
||||
e.fromTag(nbttagcompound);
|
||||
e.setUuid(uUID);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// "dimension" []
|
||||
// "item" []
|
||||
// "count", []
|
||||
// "age", [check]
|
||||
// "effect_"name []
|
||||
// "hold" [inventory_set?]
|
||||
// "hold_offhand" [inventory_set?]
|
||||
// "jump" [check]
|
||||
// "nbt" <-big one, for now use run('data merge entity ...
|
||||
}};
|
||||
|
||||
public void setEvent(CarpetContext cc, String eventName, FunctionValue fun, List<Value> args)
|
||||
@@ -1001,4 +1038,14 @@ public class EntityValue extends Value
|
||||
throw new InternalExpressionException("Unknown entity event: " + eventName);
|
||||
((EntityInterface)entity).getEventContainer().addEvent(event, cc, fun, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.put("Data", getEntity().toTag( new CompoundTag()));
|
||||
tag.put("Name", StringTag.of(Registry.ENTITY_TYPE.getId(entity.getType()).toString()));
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.text.BaseText;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public class FormattedTextValue extends StringValue
|
||||
{
|
||||
@@ -37,4 +40,11 @@ public class FormattedTextValue extends StringValue
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
|
||||
return StringTag.of(Text.Serializer.toJson(text));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
public abstract class FrameworkValue extends Value
|
||||
{
|
||||
@Override
|
||||
@@ -25,4 +27,10 @@ public abstract class FrameworkValue extends Value
|
||||
{
|
||||
throw new UnsupportedOperationException("Scarpet language component cannot be used as map key");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
throw new UnsupportedOperationException("Scarpet language component cannot be serialized to the tag");
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,8 @@ import carpet.script.exception.ExpressionException;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import carpet.script.exception.ReturnStatement;
|
||||
import carpet.script.exception.ThrowStatement;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -94,6 +96,8 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
|
||||
return name.hashCode()+(int)variant;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
@@ -231,4 +235,11 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
|
||||
{
|
||||
return args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
|
||||
return StringTag.of(getString());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
public class GlobalValue extends Value
|
||||
{
|
||||
@@ -28,4 +29,10 @@ public class GlobalValue extends Value
|
||||
{
|
||||
throw new UnsupportedOperationException("Global value cannot be used as a map key");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
throw new UnsupportedOperationException("Global value cannot be serialized to the tag");
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@@ -152,4 +154,11 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
|
||||
{
|
||||
return ("i"+getString()).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
|
||||
return StringTag.of(getString());
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,23 @@ package carpet.script.value;
|
||||
import carpet.script.LazyValue;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.AbstractNumberTag;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.DoubleTag;
|
||||
import net.minecraft.nbt.IntTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.LongTag;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
@@ -98,6 +108,13 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
||||
{
|
||||
return ListValue.wrap(Arrays.asList(list));
|
||||
}
|
||||
public static ListValue ofNums(Number ... list)
|
||||
{
|
||||
List<Value> valList = new ArrayList<>();
|
||||
for (Number i : list)
|
||||
valList.add(new NumericValue(i.doubleValue()));
|
||||
return ListValue.wrap(valList);
|
||||
}
|
||||
|
||||
public static LazyValue lazyEmpty()
|
||||
{
|
||||
@@ -447,4 +464,65 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
||||
{
|
||||
return items.hashCode();
|
||||
}
|
||||
|
||||
private enum TagTypeCompat
|
||||
{
|
||||
INT,
|
||||
LONG,
|
||||
DBL,
|
||||
LIST,
|
||||
MAP,
|
||||
STRING;
|
||||
private static TagTypeCompat getType(Tag tag)
|
||||
{
|
||||
if (tag instanceof IntTag) return INT;
|
||||
if (tag instanceof LongTag) return LONG;
|
||||
if (tag instanceof DoubleTag) return DBL;
|
||||
if (tag instanceof ListTag) return LIST;
|
||||
if (tag instanceof CompoundTag) return MAP;
|
||||
return STRING;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
int argSize = items.size();
|
||||
if (argSize == 0) return new ListTag();
|
||||
ListTag tag = new ListTag();
|
||||
if (argSize ==1)
|
||||
{
|
||||
tag.add(items.get(0).toTag(force));
|
||||
return tag;
|
||||
}
|
||||
// figuring out the types
|
||||
List<Tag> tags= new ArrayList<>();
|
||||
items.forEach(v -> tags.add(v.toTag(force)));
|
||||
Set<TagTypeCompat> cases = EnumSet.noneOf(TagTypeCompat.class);
|
||||
tags.forEach(t -> cases.add(TagTypeCompat.getType(t)));
|
||||
if (cases.size()==1) // well, one type of items
|
||||
{
|
||||
tag.addAll(tags);
|
||||
return tag;
|
||||
}
|
||||
if (cases.contains(TagTypeCompat.LIST)
|
||||
|| cases.contains(TagTypeCompat.MAP)
|
||||
|| cases.contains(TagTypeCompat.STRING)) // incompatible types
|
||||
{
|
||||
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
|
||||
tags.forEach(t -> tag.add(StringTag.of(t.asString())));
|
||||
return tag;
|
||||
}
|
||||
// only numbers / mixed types
|
||||
if (cases.contains(TagTypeCompat.DBL))
|
||||
{
|
||||
tags.forEach(t -> tag.add(DoubleTag.of(((AbstractNumberTag)t).getDouble())));
|
||||
}
|
||||
else
|
||||
{
|
||||
tags.forEach(t -> tag.add(LongTag.of(((AbstractNumberTag)t).getLong())));
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -226,4 +228,16 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
|
||||
{
|
||||
return map.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
CompoundTag tag = new CompoundTag() ;
|
||||
map.forEach( (k, v) ->
|
||||
{
|
||||
if (!force && !(k instanceof StringValue)) throw new NBTSerializableValue.IncompatibleTypeException(k);
|
||||
tag.put(k.getString(), v.toTag(force));
|
||||
});
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -48,6 +49,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
private String nbtString = null;
|
||||
private Tag nbtTag = null;
|
||||
private Supplier<Tag> nbtSupplier = null;
|
||||
private boolean owned = false;
|
||||
|
||||
private NBTSerializableValue() {}
|
||||
|
||||
@@ -64,11 +66,18 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
throw new InternalExpressionException("Incorrect NBT data: "+nbtString);
|
||||
}
|
||||
};
|
||||
owned = true;
|
||||
}
|
||||
|
||||
public NBTSerializableValue(Tag tag)
|
||||
{
|
||||
nbtTag = tag;
|
||||
owned = true;
|
||||
}
|
||||
|
||||
public NBTSerializableValue(Supplier<Tag> tagSupplier)
|
||||
{
|
||||
nbtSupplier = tagSupplier;
|
||||
}
|
||||
|
||||
public static Value fromStack(ItemStack stack)
|
||||
@@ -100,7 +109,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
}
|
||||
catch (CommandSyntaxException e)
|
||||
{
|
||||
return null;
|
||||
throw new InternalExpressionException("Incorrect NBT tag: nbtString");
|
||||
}
|
||||
NBTSerializableValue value = new NBTSerializableValue(tag);
|
||||
value.nbtString = nbtString;
|
||||
@@ -115,6 +124,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
NBTSerializableValue copy = new NBTSerializableValue(nbtTag);
|
||||
copy.nbtSupplier = this.nbtSupplier;
|
||||
copy.nbtString = this.nbtString;
|
||||
copy.owned = this.owned;
|
||||
return copy;
|
||||
}
|
||||
|
||||
@@ -122,9 +132,8 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
public Value deepcopy()
|
||||
{
|
||||
NBTSerializableValue copy = (NBTSerializableValue) clone();
|
||||
// same fields except when tag is set - need to copy it.
|
||||
if (copy.nbtTag != null)
|
||||
copy.nbtTag = copy.getTag().copy();
|
||||
copy.owned = false;
|
||||
ensureOwnership();
|
||||
return copy;
|
||||
}
|
||||
|
||||
@@ -290,7 +299,50 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
private static Value decodeTag(Tag t)
|
||||
{
|
||||
if (t instanceof CompoundTag)
|
||||
return new NBTSerializableValue(t);
|
||||
return new NBTSerializableValue(() -> t);
|
||||
if (t instanceof AbstractNumberTag)
|
||||
return new NumericValue(((AbstractNumberTag) t).getDouble());
|
||||
// more can be done here
|
||||
return new StringValue(t.asString());
|
||||
}
|
||||
|
||||
public Value toValue()
|
||||
{
|
||||
return decodeTagDeep(this.getTag());
|
||||
}
|
||||
|
||||
public static Value fromValue(Value v)
|
||||
{
|
||||
if (v instanceof NBTSerializableValue)
|
||||
return v;
|
||||
if (v instanceof NullValue)
|
||||
return Value.NULL;
|
||||
return NBTSerializableValue.parseString(v.getString());
|
||||
}
|
||||
|
||||
|
||||
private static Value decodeTagDeep(Tag t)
|
||||
{
|
||||
if (t instanceof CompoundTag)
|
||||
{
|
||||
Map<Value, Value> pairs = new HashMap<>();
|
||||
CompoundTag ctag = (CompoundTag)t;
|
||||
for (String key: ctag.getKeys())
|
||||
{
|
||||
pairs.put(new StringValue(key), decodeTagDeep(ctag.get(key)));
|
||||
}
|
||||
return MapValue.wrap(pairs);
|
||||
}
|
||||
if (t instanceof AbstractListTag)
|
||||
{
|
||||
List<Value> elems = new ArrayList<>();
|
||||
AbstractListTag<? extends Tag> ltag = (AbstractListTag<? extends Tag>)t;
|
||||
for (Tag elem: ltag)
|
||||
{
|
||||
elems.add(decodeTagDeep(elem));
|
||||
}
|
||||
return ListValue.wrap(elems);
|
||||
}
|
||||
if (t instanceof AbstractNumberTag)
|
||||
return new NumericValue(((AbstractNumberTag) t).getDouble());
|
||||
// more can be done here
|
||||
@@ -304,13 +356,6 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
return nbtTag;
|
||||
}
|
||||
|
||||
private void replaceTag(Tag newTag)
|
||||
{
|
||||
nbtTag = newTag;
|
||||
nbtString = null;
|
||||
nbtSupplier = null; // just to be sure
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o)
|
||||
{
|
||||
@@ -346,6 +391,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
{
|
||||
try
|
||||
{
|
||||
ensureOwnership();
|
||||
return (CompoundTag) getTag();
|
||||
}
|
||||
catch (ClassCastException e)
|
||||
@@ -364,12 +410,12 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
public boolean put(Value where, Value value, Value conditions)
|
||||
{
|
||||
/// WIP
|
||||
|
||||
ensureOwnership();
|
||||
NbtPathArgumentType.NbtPath path = cachePath(where.getString());
|
||||
Tag tagToInsert = value instanceof NBTSerializableValue ?
|
||||
((NBTSerializableValue) value).getTag() :
|
||||
new NBTSerializableValue(value.getString()).getTag();
|
||||
Tag modifiedTag;
|
||||
boolean modifiedTag;
|
||||
if (conditions instanceof NumericValue)
|
||||
{
|
||||
modifiedTag = modify_insert((int)((NumericValue) conditions).getLong(), path, tagToInsert);
|
||||
@@ -390,22 +436,17 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (modifiedTag != null)
|
||||
{
|
||||
replaceTag(modifiedTag);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return modifiedTag;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Tag modify_insert(int index, NbtPathArgumentType.NbtPath nbtPath, Tag newElement)
|
||||
private boolean modify_insert(int index, NbtPathArgumentType.NbtPath nbtPath, Tag newElement)
|
||||
{
|
||||
return modify_insert(index, nbtPath, newElement, this.getTag().copy());
|
||||
return modify_insert(index, nbtPath, newElement, this.getTag());
|
||||
}
|
||||
|
||||
private Tag modify_insert(int index, NbtPathArgumentType.NbtPath nbtPath, Tag newElement, Tag currentTag)
|
||||
private boolean modify_insert(int index, NbtPathArgumentType.NbtPath nbtPath, Tag newElement, Tag currentTag)
|
||||
{
|
||||
Collection<Tag> targets;
|
||||
try
|
||||
@@ -414,7 +455,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
}
|
||||
catch (CommandSyntaxException e)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean modified = false;
|
||||
@@ -428,27 +469,27 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
{
|
||||
AbstractListTag<?> targetList = (AbstractListTag) target;
|
||||
if (!targetList.addTag(index < 0 ? targetList.size() + index + 1 : index, newElement.copy()))
|
||||
return null;
|
||||
return false;
|
||||
modified = true;
|
||||
}
|
||||
catch (IndexOutOfBoundsException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
return modified?currentTag:null;
|
||||
return modified;
|
||||
}
|
||||
|
||||
|
||||
private Tag modify_merge(NbtPathArgumentType.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1)
|
||||
private boolean modify_merge(NbtPathArgumentType.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1)
|
||||
{
|
||||
if (!(replacement instanceof CompoundTag))
|
||||
{
|
||||
return getTag();
|
||||
return false;
|
||||
}
|
||||
Tag originalTag = getTag().copy();
|
||||
Tag ownTag = getTag();
|
||||
try
|
||||
{
|
||||
for (Tag target : nbtPath.getOrInit(originalTag, CompoundTag::new))
|
||||
for (Tag target : nbtPath.getOrInit(ownTag, CompoundTag::new))
|
||||
{
|
||||
if (!(target instanceof CompoundTag))
|
||||
{
|
||||
@@ -457,23 +498,26 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
((CompoundTag) target).copyFrom((CompoundTag) replacement);
|
||||
}
|
||||
}
|
||||
catch (CommandSyntaxException ignored) { }
|
||||
return originalTag;
|
||||
catch (CommandSyntaxException ignored)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Tag modify_replace(NbtPathArgumentType.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1)
|
||||
private boolean modify_replace(NbtPathArgumentType.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1)
|
||||
{
|
||||
Tag originalTag = getTag().copy();
|
||||
Tag tag = getTag();
|
||||
String pathText = nbtPath.toString();
|
||||
if (pathText.endsWith("]")) // workaround for array replacement or item in the array replacement
|
||||
{
|
||||
if (nbtPath.remove(originalTag)==0)
|
||||
return null;
|
||||
if (nbtPath.remove(tag)==0)
|
||||
return false;
|
||||
Pattern pattern = Pattern.compile("\\[[^\\[]*]$");
|
||||
Matcher matcher = pattern.matcher(pathText);
|
||||
if (!matcher.find()) // malformed path
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
String arrAccess = matcher.group();
|
||||
int pos;
|
||||
@@ -487,21 +531,21 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
NbtPathArgumentType.NbtPath newPath = cachePath(pathText.substring(0, pathText.length()-arrAccess.length()));
|
||||
return modify_insert(pos,newPath,replacement, originalTag);
|
||||
return modify_insert(pos,newPath,replacement, tag);
|
||||
}
|
||||
try
|
||||
{
|
||||
nbtPath.put(originalTag, () -> replacement);
|
||||
nbtPath.put(tag, () -> replacement);
|
||||
}
|
||||
catch (CommandSyntaxException e)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
return originalTag;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -527,13 +571,23 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
return cachePath(where.getString()).count(getTag()) > 0;
|
||||
}
|
||||
|
||||
private void ensureOwnership()
|
||||
{
|
||||
if (!owned)
|
||||
{
|
||||
nbtTag = getTag().copy();
|
||||
nbtString = null;
|
||||
nbtSupplier = null; // just to be sure
|
||||
owned = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(Value where)
|
||||
{
|
||||
NbtPathArgumentType.NbtPath path = cachePath(where.getString());
|
||||
Tag tag = getTag().copy();
|
||||
int removed = path.remove(tag);
|
||||
if (removed > 0) replaceTag(tag);
|
||||
ensureOwnership();
|
||||
int removed = path.remove(getTag());
|
||||
return removed > 0;
|
||||
}
|
||||
|
||||
@@ -584,4 +638,23 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
{
|
||||
return "nbt";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
|
||||
ensureOwnership();
|
||||
return getTag();
|
||||
}
|
||||
|
||||
public static class IncompatibleTypeException extends RuntimeException
|
||||
{
|
||||
private IncompatibleTypeException() {}
|
||||
public Value val;
|
||||
public IncompatibleTypeException(Value val)
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
public class NullValue extends NumericValue // TODO check nonsingleton code
|
||||
{
|
||||
@Override
|
||||
@@ -50,4 +53,11 @@ public class NullValue extends NumericValue // TODO check nonsingleton code
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
|
||||
return StringTag.of("null");
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import net.minecraft.nbt.DoubleTag;
|
||||
import net.minecraft.nbt.IntTag;
|
||||
import net.minecraft.nbt.LongTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@@ -204,4 +208,20 @@ public class NumericValue extends Value
|
||||
{
|
||||
return (int)getLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
long longValue = getLong();
|
||||
if (value == (double)longValue)
|
||||
{
|
||||
if (abs(value) < Integer.MAX_VALUE-2)
|
||||
return IntTag.of((int)longValue);
|
||||
return LongTag.of(getLong());
|
||||
}
|
||||
else
|
||||
{
|
||||
return DoubleTag.of(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
public class StringValue extends Value
|
||||
{
|
||||
private String str;
|
||||
@@ -30,4 +33,10 @@ public class StringValue extends Value
|
||||
{
|
||||
return "string";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
return StringTag.of(str);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import carpet.script.LazyValue;
|
||||
import carpet.script.Tokenizer;
|
||||
import carpet.script.exception.ExpressionException;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -144,4 +145,10 @@ public class ThreadValue extends Value
|
||||
locks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag toTag(boolean force)
|
||||
{
|
||||
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
|
||||
return getValue().toTag(true);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -203,4 +204,6 @@ public abstract class Value implements Comparable<Value>, Cloneable
|
||||
throw new InternalExpressionException("Cannot make a copy of value: "+this);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Tag toTag(boolean force);
|
||||
}
|
||||
Reference in new issue
Block a user