Merge branch 'master' into 1.15
# Conflicts: # src/main/java/carpet/script/CarpetExpression.java
This commit is contained in:
commit
7fae5c92cf
20 files changed
+553
-138
No files matched your search
@@ -111,6 +111,7 @@ public class CarpetServer // static for now - easier to handle all around the co
|
|||||||
|
|
||||||
public static void onServerClosed(MinecraftServer server)
|
public static void onServerClosed(MinecraftServer server)
|
||||||
{
|
{
|
||||||
|
scriptServer.onClose();
|
||||||
LoggerRegistry.stopLoggers();
|
LoggerRegistry.stopLoggers();
|
||||||
extensions.forEach(e -> e.onServerClosed(server));
|
extensions.forEach(e -> e.onServerClosed(server));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package carpet.mixins;
|
||||||
|
|
||||||
|
import carpet.settings.CarpetSettings;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.entity.EntityCategory;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.IWorld;
|
||||||
|
import net.minecraft.world.biome.Biome;
|
||||||
|
import net.minecraft.world.biome.source.BiomeSource;
|
||||||
|
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
||||||
|
import net.minecraft.world.gen.chunk.FlatChunkGenerator;
|
||||||
|
import net.minecraft.world.gen.chunk.FlatChunkGeneratorConfig;
|
||||||
|
import net.minecraft.world.gen.feature.Feature;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mixin(FlatChunkGenerator.class)
|
||||||
|
public abstract class FlatChunkGeneratorMixin extends ChunkGenerator<FlatChunkGeneratorConfig>
|
||||||
|
{
|
||||||
|
public FlatChunkGeneratorMixin(IWorld iWorld, BiomeSource biome, FlatChunkGeneratorConfig chunkGeneratorConfig)
|
||||||
|
{
|
||||||
|
super(iWorld, biome, chunkGeneratorConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Biome.SpawnEntry> getEntitySpawnList(EntityCategory category, BlockPos pos)
|
||||||
|
{
|
||||||
|
if (CarpetSettings.flatWorldStructureSpawning)
|
||||||
|
{
|
||||||
|
if (Feature.SWAMP_HUT.method_14029(this.world, pos))
|
||||||
|
{
|
||||||
|
if (category == EntityCategory.MONSTER)
|
||||||
|
{
|
||||||
|
return Feature.SWAMP_HUT.getMonsterSpawns();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (category == EntityCategory.CREATURE)
|
||||||
|
{
|
||||||
|
return Feature.SWAMP_HUT.getCreatureSpawns();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (category == EntityCategory.MONSTER)
|
||||||
|
{
|
||||||
|
if (Feature.PILLAGER_OUTPOST.isApproximatelyInsideStructure(this.world, pos))
|
||||||
|
{
|
||||||
|
return Feature.PILLAGER_OUTPOST.getMonsterSpawns();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CarpetSettings.huskSpawningInTemples)
|
||||||
|
{
|
||||||
|
if (Feature.DESERT_PYRAMID.isApproximatelyInsideStructure(this.world, pos))
|
||||||
|
{
|
||||||
|
return Feature.DESERT_PYRAMID.getMonsterSpawns();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Feature.OCEAN_MONUMENT.isApproximatelyInsideStructure(this.world, pos))
|
||||||
|
{
|
||||||
|
return Feature.OCEAN_MONUMENT.getMonsterSpawns();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Feature.NETHER_BRIDGE.isInsideStructure(this.world, pos))
|
||||||
|
{
|
||||||
|
return Feature.NETHER_BRIDGE.getMonsterSpawns();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Feature.NETHER_BRIDGE.isApproximatelyInsideStructure(this.world, pos) && this.world.getBlockState(pos.down()).getBlock() == Blocks.NETHER_BRICKS)
|
||||||
|
{
|
||||||
|
return Feature.NETHER_BRIDGE.getMonsterSpawns();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CarpetSettings.shulkerSpawningInEndCities)
|
||||||
|
{
|
||||||
|
if (Feature.END_CITY.isInsideStructure(this.world, pos))
|
||||||
|
{
|
||||||
|
return Feature.END_CITY.getMonsterSpawns();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getEntitySpawnList(category, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,6 +54,7 @@ import net.minecraft.item.ItemStack;
|
|||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.item.NetworkSyncedItem;
|
import net.minecraft.item.NetworkSyncedItem;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.network.Packet;
|
import net.minecraft.network.Packet;
|
||||||
import net.minecraft.particle.ParticleEffect;
|
import net.minecraft.particle.ParticleEffect;
|
||||||
import net.minecraft.predicate.entity.EntityPredicates;
|
import net.minecraft.predicate.entity.EntityPredicates;
|
||||||
@@ -2888,6 +2889,34 @@ public class CarpetExpression
|
|||||||
CarpetServer.scriptServer.events.scheduleCall(cc, funname, args, delay);
|
CarpetServer.scriptServer.events.scheduleCall(cc, funname, args, delay);
|
||||||
return (c_, t_) -> Value.TRUE;
|
return (c_, t_) -> Value.TRUE;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.expr.addLazyFunction("get_global_state", -1, (c, t, lv) ->
|
||||||
|
{
|
||||||
|
String file = null;
|
||||||
|
if (lv.size()>0)
|
||||||
|
file = lv.get(0).evalValue(c).getString();
|
||||||
|
Tag state = ((CarpetContext)c).host.getGlobalState(file);
|
||||||
|
if (state == null)
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value retVal = new NBTSerializableValue(state);
|
||||||
|
return (cc, tt) -> retVal;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.expr.addLazyFunction("set_global_state", -1, (c, t, lv) ->
|
||||||
|
{
|
||||||
|
if (lv.size() == 0)
|
||||||
|
throw new InternalExpressionException("save_state needs nbt tag and optional file");
|
||||||
|
Value val = lv.get(0).evalValue(c);
|
||||||
|
String file = null;
|
||||||
|
if (lv.size()>1)
|
||||||
|
file = lv.get(1).evalValue(c).getString();
|
||||||
|
NBTSerializableValue tagValue = (val instanceof NBTSerializableValue)
|
||||||
|
? (NBTSerializableValue) val
|
||||||
|
: new NBTSerializableValue(val.getString());
|
||||||
|
Tag tag = tagValue.getTag();
|
||||||
|
((CarpetContext)c).host.setGlobalState(tag, file);
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public class CarpetScriptServer
|
|||||||
|
|
||||||
private ScriptHost createMinecraftScriptHost(String name, ModuleInterface module, boolean perPlayer, ServerCommandSource source)
|
private ScriptHost createMinecraftScriptHost(String name, ModuleInterface module, boolean perPlayer, ServerCommandSource source)
|
||||||
{
|
{
|
||||||
ScriptHost host = new ScriptHost(name, module, perPlayer );
|
ScriptHost host = new ScriptHost(name, module, perPlayer, null );
|
||||||
host.globalVariables.put("_x", (c, t) -> Value.ZERO);
|
host.globalVariables.put("_x", (c, t) -> Value.ZERO);
|
||||||
host.globalVariables.put("_y", (c, t) -> Value.ZERO);
|
host.globalVariables.put("_y", (c, t) -> Value.ZERO);
|
||||||
host.globalVariables.put("_z", (c, t) -> Value.ZERO);
|
host.globalVariables.put("_z", (c, t) -> Value.ZERO);
|
||||||
@@ -360,5 +360,17 @@ public class CarpetScriptServer
|
|||||||
public void tick()
|
public void tick()
|
||||||
{
|
{
|
||||||
events.tick();
|
events.tick();
|
||||||
|
for (ScriptHost host : modules.values())
|
||||||
|
{
|
||||||
|
host.tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClose()
|
||||||
|
{
|
||||||
|
for (ScriptHost host : modules.values())
|
||||||
|
{
|
||||||
|
host.onClose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,7 @@ public class Context
|
|||||||
static final int ITERATOR = 6;
|
static final int ITERATOR = 6;
|
||||||
static final int SIGNATURE = 7;
|
static final int SIGNATURE = 7;
|
||||||
static final int LOCALIZATION = 8;
|
static final int LOCALIZATION = 8;
|
||||||
|
static final int LVALUE = 9;
|
||||||
|
|
||||||
private Map<String, LazyValue> variables = new HashMap<>();
|
private Map<String, LazyValue> variables = new HashMap<>();
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import carpet.script.value.AbstractListValue;
|
|||||||
import carpet.script.value.ContainerValueInterface;
|
import carpet.script.value.ContainerValueInterface;
|
||||||
import carpet.script.value.FunctionSignatureValue;
|
import carpet.script.value.FunctionSignatureValue;
|
||||||
import carpet.script.value.GlobalValue;
|
import carpet.script.value.GlobalValue;
|
||||||
|
import carpet.script.value.LContainerValue;
|
||||||
import carpet.script.value.LazyListValue;
|
import carpet.script.value.LazyListValue;
|
||||||
import carpet.script.value.ListValue;
|
import carpet.script.value.ListValue;
|
||||||
import carpet.script.value.MapValue;
|
import carpet.script.value.MapValue;
|
||||||
@@ -336,7 +337,7 @@ import static java.lang.Math.min;
|
|||||||
public class Expression implements Cloneable
|
public class Expression implements Cloneable
|
||||||
{
|
{
|
||||||
private static final Map<String, Integer> precedence = new HashMap<String,Integer>() {{
|
private static final Map<String, Integer> precedence = new HashMap<String,Integer>() {{
|
||||||
put("attribute~.", 80);
|
put("attribute~:", 80);
|
||||||
put("unary+-!", 60);
|
put("unary+-!", 60);
|
||||||
put("exponent^", 40);
|
put("exponent^", 40);
|
||||||
put("multiplication*/%", 30);
|
put("multiplication*/%", 30);
|
||||||
@@ -1071,7 +1072,7 @@ public class Expression implements Cloneable
|
|||||||
* even if they look like them:
|
* even if they look like them:
|
||||||
* </p>
|
* </p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Match, Get <code>~ .</code></li>
|
* <li>Match, Get <code>~ :</code></li>
|
||||||
* <li>Unary <code>+ - !</code></li>
|
* <li>Unary <code>+ - !</code></li>
|
||||||
* <li>Exponent <code>^</code></li>
|
* <li>Exponent <code>^</code></li>
|
||||||
* <li>Multiplication <code>* / %</code></li>
|
* <li>Multiplication <code>* / %</code></li>
|
||||||
@@ -1086,7 +1087,7 @@ public class Expression implements Cloneable
|
|||||||
* <li>Bracket <code>( )</code></li>
|
* <li>Bracket <code>( )</code></li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <h3><code>Get, Accessor Operator .</code></h3>
|
* <h3><code>Get, Accessor Operator :</code></h3>
|
||||||
* <p>Operator version of the <code>get(...)</code> function to access elements of lists, maps, and potentially other
|
* <p>Operator version of the <code>get(...)</code> function to access elements of lists, maps, and potentially other
|
||||||
* containers (i.e. NBTs). It is important to distinguish from <code>~</code> operator, which is a matching operator,
|
* containers (i.e. NBTs). It is important to distinguish from <code>~</code> operator, which is a matching operator,
|
||||||
* which is expected to perform some extra computations to retrieve the result, while <code>.</code> should be
|
* which is expected to perform some extra computations to retrieve the result, while <code>.</code> should be
|
||||||
@@ -1094,7 +1095,7 @@ public class Expression implements Cloneable
|
|||||||
* API, meaning <code>get(...)</code>, <code>put(...)</code>, <code>delete(...)</code>,
|
* API, meaning <code>get(...)</code>, <code>put(...)</code>, <code>delete(...)</code>,
|
||||||
* and <code>has(...)</code> functions</p>
|
* and <code>has(...)</code> functions</p>
|
||||||
* <p>WARNING: Unlike for some languages, where item access operator can be an L-value, to assign new values to
|
* <p>WARNING: Unlike for some languages, where item access operator can be an L-value, to assign new values to
|
||||||
* container elements, use <code>put</code> function instead, i.e. <code>a.1='foo'</code> won't work.</p>
|
* container elements, use <code>put</code> function instead, i.e. <code>a:1='foo'</code> won't work.</p>
|
||||||
*
|
*
|
||||||
* <h3><code>Matching Operator ~</code></h3>
|
* <h3><code>Matching Operator ~</code></h3>
|
||||||
* <p>This operator should be understood as 'matches', 'contains', 'is_in',
|
* <p>This operator should be understood as 'matches', 'contains', 'is_in',
|
||||||
@@ -1242,12 +1243,6 @@ public class Expression implements Cloneable
|
|||||||
*/
|
*/
|
||||||
public void Operators()
|
public void Operators()
|
||||||
{
|
{
|
||||||
addBinaryOperator(".", precedence.get("attribute~."),true, (container, key) ->
|
|
||||||
{
|
|
||||||
if (container instanceof ContainerValueInterface)
|
|
||||||
return ((ContainerValueInterface) container).get(key);
|
|
||||||
throw new InternalExpressionException("Cannot access elements of a non-container");
|
|
||||||
});
|
|
||||||
addBinaryOperator("+", precedence.get("addition+-"), true, Value::add);
|
addBinaryOperator("+", precedence.get("addition+-"), true, Value::add);
|
||||||
addBinaryOperator("-", precedence.get("addition+-"), true, Value::subtract);
|
addBinaryOperator("-", precedence.get("addition+-"), true, Value::subtract);
|
||||||
addBinaryOperator("*", precedence.get("multiplication*/%"), true, Value::multiply);
|
addBinaryOperator("*", precedence.get("multiplication*/%"), true, Value::multiply);
|
||||||
@@ -1273,7 +1268,7 @@ public class Expression implements Cloneable
|
|||||||
return v2.getBoolean() ? ((cc, tt) -> v2) : LazyValue.FALSE;
|
return v2.getBoolean() ? ((cc, tt) -> v2) : LazyValue.FALSE;
|
||||||
});
|
});
|
||||||
|
|
||||||
addBinaryOperator("~", precedence.get("attribute~."), true, Value::in);
|
addBinaryOperator("~", precedence.get("attribute~:"), true, Value::in);
|
||||||
|
|
||||||
addBinaryOperator(">", precedence.get("compare>=><=<"), false, (v1, v2) ->
|
addBinaryOperator(">", precedence.get("compare>=><=<"), false, (v1, v2) ->
|
||||||
v1.compareTo(v2) > 0 ? Value.TRUE : Value.FALSE);
|
v1.compareTo(v2) > 0 ? Value.TRUE : Value.FALSE);
|
||||||
@@ -1290,7 +1285,7 @@ public class Expression implements Cloneable
|
|||||||
|
|
||||||
addLazyBinaryOperator("=", precedence.get("assign=<>"), false, (c, t, lv1, lv2) ->
|
addLazyBinaryOperator("=", precedence.get("assign=<>"), false, (c, t, lv1, lv2) ->
|
||||||
{
|
{
|
||||||
Value v1 = lv1.evalValue(c);
|
Value v1 = lv1.evalValue(c, Context.LVALUE);
|
||||||
Value v2 = lv2.evalValue(c);
|
Value v2 = lv2.evalValue(c);
|
||||||
if (v1 instanceof ListValue.ListConstructorValue && v2 instanceof ListValue)
|
if (v1 instanceof ListValue.ListConstructorValue && v2 instanceof ListValue)
|
||||||
{
|
{
|
||||||
@@ -1309,6 +1304,15 @@ public class Expression implements Cloneable
|
|||||||
}
|
}
|
||||||
return (cc, tt) -> Value.TRUE;
|
return (cc, tt) -> Value.TRUE;
|
||||||
}
|
}
|
||||||
|
if (v1 instanceof LContainerValue)
|
||||||
|
{
|
||||||
|
ContainerValueInterface container = ((LContainerValue) v1).getContainer();
|
||||||
|
if (container == null)
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value address = ((LContainerValue) v1).getAddress();
|
||||||
|
if (!(container.put(address, v2))) return (cc, tt) -> Value.NULL;
|
||||||
|
return (cc, tt) -> v2;
|
||||||
|
}
|
||||||
v1.assertAssignable();
|
v1.assertAssignable();
|
||||||
String varname = v1.getVariable();
|
String varname = v1.getVariable();
|
||||||
Value copy = v2.reboundedTo(varname);
|
Value copy = v2.reboundedTo(varname);
|
||||||
@@ -2009,7 +2013,7 @@ public class Expression implements Cloneable
|
|||||||
* <p>Here is a list of operations that work on all types of containers: lists, maps, as well as other Minecraft
|
* <p>Here is a list of operations that work on all types of containers: lists, maps, as well as other Minecraft
|
||||||
* specific modifyable containers, like NBTs</p>
|
* specific modifyable containers, like NBTs</p>
|
||||||
*
|
*
|
||||||
* <h3><code>get(container, address), '.' operator</code></h3>
|
* <h3><code>get(container, address), ':' operator</code></h3>
|
||||||
* <p>Returns the value at <code>address</code> element from the <code>value</code>.
|
* <p>Returns the value at <code>address</code> element from the <code>value</code>.
|
||||||
* For lists it indicates an index, use negative numbers to reach elements from the end of the list. <code>get</code>
|
* For lists it indicates an index, use negative numbers to reach elements from the end of the list. <code>get</code>
|
||||||
* call will always be able to find the index. In case there is few items, it will loop over </p>
|
* call will always be able to find the index. In case there is few items, it will loop over </p>
|
||||||
@@ -2022,7 +2026,7 @@ public class Expression implements Cloneable
|
|||||||
* get(l(range(10)), 5) => 5
|
* get(l(range(10)), 5) => 5
|
||||||
* get(l(range(10)), -1) => 9
|
* get(l(range(10)), -1) => 9
|
||||||
* get(l(range(10)), 10) => 0
|
* get(l(range(10)), 10) => 0
|
||||||
* l(range(10)).93 => 3
|
* l(range(10)):93 => 3
|
||||||
*
|
*
|
||||||
* get(player() ~ 'nbt', 'Health') => 20 // inefficient way to get player health, use player() ~ 'health' instead
|
* get(player() ~ 'nbt', 'Health') => 20 // inefficient way to get player health, use player() ~ 'health' instead
|
||||||
*
|
*
|
||||||
@@ -2318,13 +2322,13 @@ public class Expression implements Cloneable
|
|||||||
addUnaryFunction("keys", v -> {
|
addUnaryFunction("keys", v -> {
|
||||||
if (v instanceof MapValue)
|
if (v instanceof MapValue)
|
||||||
return new ListValue(((MapValue) v).getMap().keySet());
|
return new ListValue(((MapValue) v).getMap().keySet());
|
||||||
throw new InternalExpressionException("keys applies only to maps");
|
return Value.NULL;
|
||||||
});
|
});
|
||||||
|
|
||||||
addUnaryFunction("values", v -> {
|
addUnaryFunction("values", v -> {
|
||||||
if (v instanceof MapValue)
|
if (v instanceof MapValue)
|
||||||
return new ListValue(((MapValue) v).getMap().values());
|
return new ListValue(((MapValue) v).getMap().values());
|
||||||
throw new InternalExpressionException("keys applies only to maps");
|
return Value.NULL;
|
||||||
});
|
});
|
||||||
|
|
||||||
addUnaryFunction("pairs", v -> {
|
addUnaryFunction("pairs", v -> {
|
||||||
@@ -2332,21 +2336,93 @@ public class Expression implements Cloneable
|
|||||||
return ListValue.wrap(((MapValue) v).getMap().entrySet().stream().map(
|
return ListValue.wrap(((MapValue) v).getMap().entrySet().stream().map(
|
||||||
(p) -> ListValue.of(p.getKey(), p.getValue())
|
(p) -> ListValue.of(p.getKey(), p.getValue())
|
||||||
).collect(Collectors.toList()));
|
).collect(Collectors.toList()));
|
||||||
throw new InternalExpressionException("pairs applies only to maps");
|
return Value.NULL;
|
||||||
});
|
});
|
||||||
|
|
||||||
addBinaryFunction("get", (container, key) ->
|
addLazyBinaryOperator(":", precedence.get("attribute~:"),true, (c, t, container_lv, key_lv) ->
|
||||||
{
|
{
|
||||||
if (container instanceof ContainerValueInterface)
|
Value container = container_lv.evalValue(c);
|
||||||
return ((ContainerValueInterface) container).get(key);
|
if (container instanceof LContainerValue)
|
||||||
throw new InternalExpressionException("Cannot access elements of a non-container");
|
{
|
||||||
|
ContainerValueInterface outerContainer = ((LContainerValue) container).getContainer();
|
||||||
|
if (outerContainer == null)
|
||||||
|
{
|
||||||
|
Value innerLValue = new LContainerValue(null, null);
|
||||||
|
return (cc, tt) -> innerLValue;
|
||||||
|
}
|
||||||
|
Value innerContainer = outerContainer.get(((LContainerValue) container).getAddress());
|
||||||
|
if (!(innerContainer instanceof ContainerValueInterface))
|
||||||
|
{
|
||||||
|
Value innerLValue = new LContainerValue(null, null);
|
||||||
|
return (cc, tt) -> innerLValue;
|
||||||
|
}
|
||||||
|
Value innerLValue = new LContainerValue((ContainerValueInterface) innerContainer, key_lv.evalValue(c));
|
||||||
|
return (cc, tt) -> innerLValue;
|
||||||
|
}
|
||||||
|
if (!(container instanceof ContainerValueInterface))
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value address = key_lv.evalValue(c);
|
||||||
|
if (t != Context.LVALUE)
|
||||||
|
{
|
||||||
|
Value retVal = ((ContainerValueInterface) container).get(address);
|
||||||
|
return (cc, ct) -> retVal;
|
||||||
|
}
|
||||||
|
Value retVal = new LContainerValue((ContainerValueInterface) container, address);
|
||||||
|
return (cc, ct) -> retVal;
|
||||||
});
|
});
|
||||||
|
|
||||||
addBinaryFunction("has", (container, key) ->
|
addLazyFunction("get", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
if (container instanceof ContainerValueInterface)
|
if (lv.size() == 0)
|
||||||
return new NumericValue(((ContainerValueInterface) container).has(key));
|
throw new InternalExpressionException("get requires parameters");
|
||||||
throw new InternalExpressionException("Cannot access elements of a non-container");
|
if (lv.size() == 1)
|
||||||
|
{
|
||||||
|
Value v = lv.get(0).evalValue(c, Context.LVALUE);
|
||||||
|
if (!(v instanceof LContainerValue))
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
ContainerValueInterface container = ((LContainerValue) v).getContainer();
|
||||||
|
if (container == null)
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value ret = container.get(((LContainerValue) v).getAddress());
|
||||||
|
return (cc, tt) -> ret;
|
||||||
|
}
|
||||||
|
Value container = lv.get(0).evalValue(c);
|
||||||
|
for (int i = 1; i < lv.size(); i++)
|
||||||
|
{
|
||||||
|
if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL;
|
||||||
|
container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c));
|
||||||
|
}
|
||||||
|
if (container == null)
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value finalContainer = container;
|
||||||
|
return (cc, tt) -> finalContainer;
|
||||||
|
});
|
||||||
|
|
||||||
|
addLazyFunction("has", -1, (c, t, lv) ->
|
||||||
|
{
|
||||||
|
if (lv.size() == 0)
|
||||||
|
throw new InternalExpressionException("get requires parameters");
|
||||||
|
if (lv.size() == 1)
|
||||||
|
{
|
||||||
|
Value v = lv.get(0).evalValue(c, Context.LVALUE);
|
||||||
|
if (!(v instanceof LContainerValue))
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
ContainerValueInterface container = ((LContainerValue) v).getContainer();
|
||||||
|
if (container == null)
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value ret = new NumericValue(container.has(((LContainerValue) v).getAddress()));
|
||||||
|
return (cc, tt) -> ret;
|
||||||
|
}
|
||||||
|
Value container = lv.get(0).evalValue(c);
|
||||||
|
for (int i = 1; i < lv.size()-1; i++)
|
||||||
|
{
|
||||||
|
if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL;
|
||||||
|
container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c));
|
||||||
|
}
|
||||||
|
if (!(container instanceof ContainerValueInterface))
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value ret = new NumericValue(((ContainerValueInterface) container).has(lv.get(lv.size()-1).evalValue(c)));
|
||||||
|
return (cc, tt) -> ret;
|
||||||
});
|
});
|
||||||
|
|
||||||
//Deprecated, use "get" instead, or . operator
|
//Deprecated, use "get" instead, or . operator
|
||||||
@@ -2363,36 +2439,69 @@ public class Expression implements Cloneable
|
|||||||
return items.get((int)index);
|
return items.get((int)index);
|
||||||
});
|
});
|
||||||
|
|
||||||
addFunction("put", (lv) ->
|
addLazyFunction("put", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
|
if(lv.size()<2)
|
||||||
|
{
|
||||||
|
throw new InternalExpressionException("put takes at least three arguments, a container, address, and values to insert at that index");
|
||||||
|
}
|
||||||
|
Value container = lv.get(0).evalValue(c, Context.LVALUE);
|
||||||
|
if (container instanceof LContainerValue)
|
||||||
|
{
|
||||||
|
ContainerValueInterface internalContainer = ((LContainerValue) container).getContainer();
|
||||||
|
if (internalContainer == null)
|
||||||
|
{
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
}
|
||||||
|
Value address = ((LContainerValue) container).getAddress();
|
||||||
|
Value what = lv.get(1).evalValue(c);
|
||||||
|
Value retVal = new NumericValue( (lv.size() > 2)
|
||||||
|
? internalContainer.put(address, what, lv.get(3).evalValue(c))
|
||||||
|
: internalContainer.put(address, what));
|
||||||
|
return (cc, tt) -> retVal;
|
||||||
|
|
||||||
|
}
|
||||||
if(lv.size()<3)
|
if(lv.size()<3)
|
||||||
{
|
{
|
||||||
throw new InternalExpressionException("put takes at least three arguments, a container, address, and values to insert at that index");
|
throw new InternalExpressionException("put takes at least three arguments, a container, address, and values to insert at that index");
|
||||||
}
|
}
|
||||||
Value container = lv.get(0);
|
|
||||||
if (!(container instanceof ContainerValueInterface))
|
if (!(container instanceof ContainerValueInterface))
|
||||||
{
|
{
|
||||||
throw new InternalExpressionException("First argument of put should be a container: list, map or nbt");
|
return (cc, tt) -> Value.NULL;
|
||||||
}
|
|
||||||
Value where = lv.get(1);
|
|
||||||
Value what = lv.get(2);
|
|
||||||
if (lv.size()>3)
|
|
||||||
{
|
|
||||||
return ((ContainerValueInterface) container).put(where, what, lv.get(3));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ((ContainerValueInterface) container).put(where, what);
|
|
||||||
}
|
}
|
||||||
|
Value where = lv.get(1).evalValue(c);
|
||||||
|
Value what = lv.get(2).evalValue(c);
|
||||||
|
Value retVal = new NumericValue( (lv.size()>3)
|
||||||
|
? ((ContainerValueInterface) container).put(where, what, lv.get(3).evalValue(c))
|
||||||
|
: ((ContainerValueInterface) container).put(where, what));
|
||||||
|
return (cc, tt) -> retVal;
|
||||||
});
|
});
|
||||||
|
|
||||||
addBinaryFunction("delete", (container, address) ->
|
addLazyFunction("delete", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
if (container instanceof ContainerValueInterface)
|
if (lv.size() == 0)
|
||||||
|
throw new InternalExpressionException("delete requires parameters");
|
||||||
|
if (lv.size() == 1)
|
||||||
{
|
{
|
||||||
return ((ContainerValueInterface) container).delete(address);
|
Value v = lv.get(0).evalValue(c, Context.LVALUE);
|
||||||
|
if (!(v instanceof LContainerValue))
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
ContainerValueInterface container = ((LContainerValue) v).getContainer();
|
||||||
|
if (container == null)
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value ret = new NumericValue(container.delete(((LContainerValue) v).getAddress()));
|
||||||
|
return (cc, tt) -> ret;
|
||||||
}
|
}
|
||||||
throw new InternalExpressionException("First argument of delete should be a container: list, map or nbt");
|
Value container = lv.get(0).evalValue(c);
|
||||||
|
for (int i = 1; i < lv.size()-1; i++)
|
||||||
|
{
|
||||||
|
if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL;
|
||||||
|
container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c));
|
||||||
|
}
|
||||||
|
if (!(container instanceof ContainerValueInterface))
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value ret = new NumericValue(((ContainerValueInterface) container).delete(lv.get(lv.size()-1).evalValue(c)));
|
||||||
|
return (cc, tt) -> ret;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import carpet.script.value.NumericValue;
|
|||||||
import carpet.script.value.StringValue;
|
import carpet.script.value.StringValue;
|
||||||
import carpet.script.value.Value;
|
import carpet.script.value.Value;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
@@ -25,18 +26,25 @@ import static java.lang.Math.max;
|
|||||||
|
|
||||||
public class ScriptHost
|
public class ScriptHost
|
||||||
{
|
{
|
||||||
public final Map<String, ScriptHost> userHosts = new HashMap<>();
|
private final Map<String, ScriptHost> userHosts = new HashMap<>();
|
||||||
public Map<String, UserDefinedFunction> globalFunctions = new HashMap<>();
|
public Map<String, UserDefinedFunction> globalFunctions = new HashMap<>();
|
||||||
public Map<String, LazyValue> globalVariables = new HashMap<>();
|
public Map<String, LazyValue> globalVariables = new HashMap<>();
|
||||||
|
|
||||||
|
private Tag globalState;
|
||||||
|
private int saveTimeout;
|
||||||
|
|
||||||
|
private ScriptHost parent;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
public String getName() {return name;}
|
public String getName() {return name;}
|
||||||
|
|
||||||
private final ModuleInterface myCode;
|
private final ModuleInterface myCode;
|
||||||
public final boolean perUser;
|
private final boolean perUser;
|
||||||
|
|
||||||
ScriptHost(String name, ModuleInterface code, boolean perUser)
|
ScriptHost(String name, ModuleInterface code, boolean perUser, ScriptHost parent)
|
||||||
{
|
{
|
||||||
|
this.saveTimeout = 0;
|
||||||
|
this.parent = parent;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.myCode = code;
|
this.myCode = code;
|
||||||
this.perUser = perUser;
|
this.perUser = perUser;
|
||||||
@@ -50,16 +58,19 @@ public class ScriptHost
|
|||||||
globalVariables.put("_", (c, t) -> Value.ZERO);
|
globalVariables.put("_", (c, t) -> Value.ZERO);
|
||||||
globalVariables.put("_i", (c, t) -> Value.ZERO);
|
globalVariables.put("_i", (c, t) -> Value.ZERO);
|
||||||
globalVariables.put("_a", (c, t) -> Value.ZERO);
|
globalVariables.put("_a", (c, t) -> Value.ZERO);
|
||||||
|
|
||||||
|
if (parent == null && name != null)
|
||||||
|
globalState = loadState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptHost retrieveForExecution(String /*Nullable*/ user)
|
private ScriptHost retrieveForExecution(String /*Nullable*/ user)
|
||||||
{
|
{
|
||||||
if (!perUser)
|
if (!perUser)
|
||||||
return this;
|
return this;
|
||||||
ScriptHost userHost = userHosts.get(user);
|
ScriptHost userHost = userHosts.get(user);
|
||||||
if (userHost != null)
|
if (userHost != null)
|
||||||
return userHost;
|
return userHost;
|
||||||
userHost = new ScriptHost(this.name, myCode, false);
|
userHost = new ScriptHost(this.name, myCode, false, this);
|
||||||
userHost.globalVariables.putAll(this.globalVariables);
|
userHost.globalVariables.putAll(this.globalVariables);
|
||||||
userHost.globalFunctions.putAll(this.globalFunctions);
|
userHost.globalFunctions.putAll(this.globalFunctions);
|
||||||
userHosts.put(user, userHost);
|
userHosts.put(user, userHost);
|
||||||
@@ -221,5 +232,60 @@ public class ScriptHost
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void dumpState()
|
||||||
|
{
|
||||||
|
myCode.saveData(null, globalState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tag loadState()
|
||||||
|
{
|
||||||
|
return myCode.getData(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tag getGlobalState(String file)
|
||||||
|
{
|
||||||
|
if (name == null || myCode.isInternal()) return null;
|
||||||
|
if (file != null)
|
||||||
|
myCode.getData(file);
|
||||||
|
if (parent == null)
|
||||||
|
return globalState;
|
||||||
|
return parent.globalState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGlobalState(Tag tag, String file)
|
||||||
|
{
|
||||||
|
if (name == null || myCode.isInternal()) return;
|
||||||
|
|
||||||
|
if (file!= null)
|
||||||
|
{
|
||||||
|
myCode.saveData(file, tag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptHost responsibleHost = (parent != null)?parent:this;
|
||||||
|
responsibleHost.globalState = tag;
|
||||||
|
if (responsibleHost.saveTimeout == 0)
|
||||||
|
{
|
||||||
|
responsibleHost.dumpState();
|
||||||
|
responsibleHost.saveTimeout = 200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick()
|
||||||
|
{
|
||||||
|
if (this.saveTimeout > 0)
|
||||||
|
{
|
||||||
|
this.saveTimeout --;
|
||||||
|
if (this.saveTimeout == 0)
|
||||||
|
{
|
||||||
|
dumpState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClose()
|
||||||
|
{
|
||||||
|
if (this.saveTimeout > 0)
|
||||||
|
dumpState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
package carpet.script.bundled;
|
package carpet.script.bundled;
|
||||||
|
|
||||||
import carpet.CarpetServer;
|
import carpet.CarpetServer;
|
||||||
|
import net.minecraft.nbt.EndTag;
|
||||||
|
import net.minecraft.nbt.PositionTracker;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -42,4 +48,76 @@ public class FileModule implements ModuleInterface
|
|||||||
{
|
{
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInternal()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//copied private method from net.minecraft.nbt.NbtIo.read()
|
||||||
|
private static Tag read(File file)
|
||||||
|
{
|
||||||
|
try (DataInputStream dataInput_1 = new DataInputStream(new FileInputStream(file)))
|
||||||
|
{
|
||||||
|
byte byte_1 = dataInput_1.readByte();
|
||||||
|
if (byte_1 == 0)
|
||||||
|
{
|
||||||
|
return new EndTag();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataInput_1.readUTF();
|
||||||
|
Tag tag_1 = Tag.createTag(byte_1);
|
||||||
|
tag_1.read(dataInput_1, 0, PositionTracker.DEFAULT);
|
||||||
|
return tag_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ignored)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//copied private method from net.minecraft.nbt.NbtIo.write() and client method safe_write
|
||||||
|
private static void write(Tag tag_1, File file)
|
||||||
|
{
|
||||||
|
File file_2 = new File(file.getAbsolutePath() + "_tmp");
|
||||||
|
if (file_2.exists()) file_2.delete();
|
||||||
|
|
||||||
|
try(DataOutputStream dataOutputStream_1 = new DataOutputStream(new FileOutputStream(file_2)))
|
||||||
|
{
|
||||||
|
dataOutputStream_1.writeByte(tag_1.getType());
|
||||||
|
if (tag_1.getType() != 0)
|
||||||
|
{
|
||||||
|
dataOutputStream_1.writeUTF("");
|
||||||
|
tag_1.write(dataOutputStream_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (file.exists()) file.delete();
|
||||||
|
if (!file.exists()) file_2.renameTo(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Tag getData(String file)
|
||||||
|
{
|
||||||
|
File dataFile =CarpetServer.minecraft_server.getLevelStorage().resolveFile(
|
||||||
|
CarpetServer.minecraft_server.getLevelName(), "scripts/"+name+".data"+(file==null?"":"."+file)+".nbt");
|
||||||
|
if (!(dataFile.isFile()))
|
||||||
|
return null;
|
||||||
|
return read(dataFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveData(String file, Tag globalState)
|
||||||
|
{
|
||||||
|
File dataFile =CarpetServer.minecraft_server.getLevelStorage().resolveFile(
|
||||||
|
CarpetServer.minecraft_server.getLevelName(), "scripts/"+name+".data"+(file==null?"":"."+file)+".nbt");
|
||||||
|
write(globalState, dataFile);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
package carpet.script.bundled;
|
package carpet.script.bundled;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
|
||||||
public interface ModuleInterface
|
public interface ModuleInterface
|
||||||
{
|
{
|
||||||
String getName();
|
String getName();
|
||||||
String getCode();
|
String getCode();
|
||||||
|
default boolean isInternal() {return true; }
|
||||||
|
default Tag getData(String file) {return null; }
|
||||||
|
default void saveData(String file, Tag globalState) {}
|
||||||
}
|
}
|
||||||
@@ -2,12 +2,12 @@ package carpet.script.value;
|
|||||||
|
|
||||||
public interface ContainerValueInterface
|
public interface ContainerValueInterface
|
||||||
{
|
{
|
||||||
public Value put(Value where, Value value);
|
boolean put(Value where, Value value);
|
||||||
default Value put(Value where, Value value, Value conditions)
|
default boolean put(Value where, Value value, Value conditions)
|
||||||
{
|
{
|
||||||
return put(where, value);
|
return put(where, value);
|
||||||
}
|
}
|
||||||
public Value get(Value where);
|
Value get(Value where);
|
||||||
public boolean has(Value where);
|
boolean has(Value where);
|
||||||
public Value delete(Value where);
|
boolean delete(Value where);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package carpet.script.value;
|
||||||
|
|
||||||
|
import carpet.script.exception.ExpressionException;
|
||||||
|
|
||||||
|
public abstract class FrameworkValue extends Value
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public String getString()
|
||||||
|
{
|
||||||
|
throw new ExpressionException("Scarpet language component cannot be used");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getBoolean()
|
||||||
|
{
|
||||||
|
throw new ExpressionException("Scarpet language component cannot be used");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Value clone()
|
||||||
|
{
|
||||||
|
throw new ExpressionException("Scarpet language component cannot be used");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException("Scarpet language component cannot be used as map key");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,29 +4,13 @@ import carpet.script.exception.ExpressionException;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class FunctionSignatureValue extends Value
|
public class FunctionSignatureValue extends FrameworkValue
|
||||||
{
|
{
|
||||||
private String identifier;
|
private String identifier;
|
||||||
private List<String> arguments;
|
private List<String> arguments;
|
||||||
private List<String> globals;
|
private List<String> globals;
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getString()
|
|
||||||
{
|
|
||||||
throw new ExpressionException("Function "+identifier+" is not defined yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean getBoolean()
|
|
||||||
{
|
|
||||||
throw new ExpressionException("Function "+identifier+" is not defined yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Value clone()
|
|
||||||
{
|
|
||||||
throw new ExpressionException("Function "+identifier+" is not defined yet");
|
|
||||||
}
|
|
||||||
public FunctionSignatureValue(String name, List<String> args, List<String> globals)
|
public FunctionSignatureValue(String name, List<String> args, List<String> globals)
|
||||||
{
|
{
|
||||||
this.identifier = name;
|
this.identifier = name;
|
||||||
@@ -43,11 +27,7 @@ public class FunctionSignatureValue extends Value
|
|||||||
}
|
}
|
||||||
public List<String> getGlobals() {return globals;}
|
public List<String> getGlobals() {return globals;}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode()
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException("function signature value cannot be used as map key");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package carpet.script.value;
|
||||||
|
|
||||||
|
public class LContainerValue extends FrameworkValue
|
||||||
|
{
|
||||||
|
private ContainerValueInterface container;
|
||||||
|
private Value address;
|
||||||
|
|
||||||
|
public LContainerValue(ContainerValueInterface c, Value v)
|
||||||
|
{
|
||||||
|
container = c;
|
||||||
|
address = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContainerValueInterface getContainer() {return container; }
|
||||||
|
public Value getAddress() {return address; }
|
||||||
|
}
|
||||||
@@ -306,7 +306,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value put(Value where, Value value, Value conditionValue)
|
public boolean put(Value where, Value value, Value conditionValue)
|
||||||
{
|
{
|
||||||
String condition = conditionValue.getString();
|
String condition = conditionValue.getString();
|
||||||
if (condition.equalsIgnoreCase("insert"))
|
if (condition.equalsIgnoreCase("insert"))
|
||||||
@@ -319,11 +319,12 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value put(Value ind, Value value)
|
public boolean put(Value ind, Value value)
|
||||||
{
|
{
|
||||||
return put(ind, value, true, false);
|
return put(ind, value, true, false);
|
||||||
}
|
}
|
||||||
private Value put(Value ind, Value value, boolean replace, boolean extend)
|
|
||||||
|
private boolean put(Value ind, Value value, boolean replace, boolean extend)
|
||||||
{
|
{
|
||||||
if (ind == Value.NULL)
|
if (ind == Value.NULL)
|
||||||
{
|
{
|
||||||
@@ -335,12 +336,14 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
{
|
{
|
||||||
items.add(value);
|
items.add(value);
|
||||||
}
|
}
|
||||||
return items.get(items.size()-1);
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int numitems = items.size();
|
int numitems = items.size();
|
||||||
int index = (int) NumericValue.asNumber(ind).getLong();
|
if (!(ind instanceof NumericValue))
|
||||||
|
return false;
|
||||||
|
int index = (int)((NumericValue) ind).getLong();
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
{
|
{
|
||||||
long range = abs(index) / numitems;
|
long range = abs(index) / numitems;
|
||||||
@@ -350,7 +353,8 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
if (replace)
|
if (replace)
|
||||||
{
|
{
|
||||||
while (index >= items.size()) items.add(Value.NULL);
|
while (index >= items.size()) items.add(Value.NULL);
|
||||||
return items.set(index, value);
|
items.set(index, value);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
while (index > items.size()) items.add(Value.NULL);
|
while (index > items.size()) items.add(Value.NULL);
|
||||||
|
|
||||||
@@ -359,11 +363,10 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
Iterable<Value> iterable = ((AbstractListValue) value)::iterator;
|
Iterable<Value> iterable = ((AbstractListValue) value)::iterator;
|
||||||
List<Value> appendix = StreamSupport.stream( iterable.spliterator(), false).collect(Collectors.toList());
|
List<Value> appendix = StreamSupport.stream( iterable.spliterator(), false).collect(Collectors.toList());
|
||||||
items.addAll(index, appendix );
|
items.addAll(index, appendix );
|
||||||
return items.get(index+appendix.size()-1);
|
return true;
|
||||||
}
|
}
|
||||||
items.add(index, value);
|
items.add(index, value);
|
||||||
return value;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,14 +389,16 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value delete(Value where)
|
public boolean delete(Value where)
|
||||||
{
|
{
|
||||||
long index = NumericValue.asNumber(where).getLong();
|
if (!(where instanceof NumericValue) || items.isEmpty()) return false;
|
||||||
|
long index = ((NumericValue) where).getLong();
|
||||||
int numitems = items.size();
|
int numitems = items.size();
|
||||||
long range = abs(index)/numitems;
|
long range = abs(index)/numitems;
|
||||||
index += (range+2)*numitems;
|
index += (range+2)*numitems;
|
||||||
index = index % numitems;
|
index = index % numitems;
|
||||||
return items.remove((int)index);
|
items.remove((int)index);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -177,21 +177,17 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value delete(Value where)
|
public boolean delete(Value where)
|
||||||
{
|
{
|
||||||
Value ret = map.remove(where);
|
Value ret = map.remove(where);
|
||||||
if (ret == null)
|
return ret != null;
|
||||||
return Value.NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value put(Value key, Value value)
|
public boolean put(Value key, Value value)
|
||||||
{
|
{
|
||||||
Value ret = map.put(key, value);
|
Value ret = map.put(key, value);
|
||||||
if (ret == null)
|
return ret != null;
|
||||||
return Value.NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
|||||||
return new StringValue(t.asString());
|
return new StringValue(t.asString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tag getTag()
|
public Tag getTag()
|
||||||
{
|
{
|
||||||
if (nbtTag == null)
|
if (nbtTag == null)
|
||||||
nbtTag = nbtSupplier.get();
|
nbtTag = nbtSupplier.get();
|
||||||
@@ -210,7 +210,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
|||||||
{
|
{
|
||||||
if (o instanceof NBTSerializableValue)
|
if (o instanceof NBTSerializableValue)
|
||||||
return getTag().equals(((NBTSerializableValue) o).getTag());
|
return getTag().equals(((NBTSerializableValue) o).getTag());
|
||||||
return super.equals((Value)o);
|
return super.equals(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -240,13 +240,13 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value put(Value where, Value value)
|
public boolean put(Value where, Value value)
|
||||||
{
|
{
|
||||||
return put(where, value, new StringValue("replace"));
|
return put(where, value, new StringValue("replace"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value put(Value where, Value value, Value conditions)
|
public boolean put(Value where, Value value, Value conditions)
|
||||||
{
|
{
|
||||||
/// WIP
|
/// WIP
|
||||||
|
|
||||||
@@ -272,14 +272,15 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return this;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (modifiedTag != null)
|
if (modifiedTag != null)
|
||||||
{
|
{
|
||||||
replaceTag(modifiedTag);
|
replaceTag(modifiedTag);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return this;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -412,13 +413,13 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value delete(Value where)
|
public boolean delete(Value where)
|
||||||
{
|
{
|
||||||
NbtPathArgumentType.NbtPath path = cachePath(where.getString());
|
NbtPathArgumentType.NbtPath path = cachePath(where.getString());
|
||||||
Tag tag = getTag().copy();
|
Tag tag = getTag().copy();
|
||||||
int removed = path.remove(tag);
|
int removed = path.remove(tag);
|
||||||
if (removed > 0) replaceTag(tag);
|
if (removed > 0) replaceTag(tag);
|
||||||
return new NumericValue(removed);
|
return removed > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class InventoryLocator
|
public static class InventoryLocator
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public abstract class Value implements Comparable<Value>, Cloneable
|
|||||||
return getString().compareTo(o.getString());
|
return getString().compareTo(o.getString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // for hashmap key access
|
@Override // for hashmap key access, and == operator
|
||||||
public boolean equals(final Object o)
|
public boolean equals(final Object o)
|
||||||
{
|
{
|
||||||
if (o instanceof Value)
|
if (o instanceof Value)
|
||||||
@@ -124,12 +124,6 @@ public abstract class Value implements Comparable<Value>, Cloneable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for general use
|
|
||||||
public boolean equals(final Value o)
|
|
||||||
{
|
|
||||||
return this.compareTo(o)==0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void assertAssignable()
|
public void assertAssignable()
|
||||||
{
|
{
|
||||||
if (boundVariable == null || boundVariable.startsWith("_"))
|
if (boundVariable == null || boundVariable.startsWith("_"))
|
||||||
|
|||||||
@@ -445,4 +445,10 @@ public class CarpetSettings
|
|||||||
category = BUGFIX
|
category = BUGFIX
|
||||||
)
|
)
|
||||||
public static boolean horseWanderingFix = false;
|
public static boolean horseWanderingFix = false;
|
||||||
|
|
||||||
|
@Rule(
|
||||||
|
desc = "Allows structure mobs to spawn in flat worlds",
|
||||||
|
category = {EXPERIMENTAL, CREATIVE}
|
||||||
|
)
|
||||||
|
public static boolean flatWorldStructureSpawning = false;
|
||||||
}
|
}
|
||||||
@@ -56,8 +56,8 @@ __add_path_segment(vector, duration, mode) ->
|
|||||||
undef('global_path_precalculated');
|
undef('global_path_precalculated');
|
||||||
if ( (l('sharp','smooth') ~ mode) == null, exit('use smooth or sharp point'));
|
if ( (l('sharp','smooth') ~ mode) == null, exit('use smooth or sharp point'));
|
||||||
if(!global_points, exit('Cannot add point to path that didn\'t started yet!'));
|
if(!global_points, exit('Cannot add point to path that didn\'t started yet!'));
|
||||||
l(v, end_time, m) = global_points.(-1);
|
l(v, end_time, m) = global_points:(-1);
|
||||||
put(vector, -2, __adjusted_rot(v.(-2) , vector.(-2) ));
|
vector:(-2) = __adjusted_rot(v:(-2) , vector:(-2) );
|
||||||
global_points += l(vector, end_time+duration, mode)
|
global_points += l(vector, end_time+duration, mode)
|
||||||
);
|
);
|
||||||
// adjusts current rotation so we don\'t spin around like crazy
|
// adjusts current rotation so we don\'t spin around like crazy
|
||||||
@@ -73,13 +73,13 @@ __adjusted_rot(previous_rot, current_rot) ->
|
|||||||
repeat(times, last_section_duration) ->
|
repeat(times, last_section_duration) ->
|
||||||
(
|
(
|
||||||
undef('global_path_precalculated');
|
undef('global_path_precalculated');
|
||||||
positions = map(global_points, _.0);
|
positions = map(global_points, _:0);
|
||||||
modes = map(global_points, _.(-1));
|
modes = map(global_points, _:(-1));
|
||||||
durations = map(global_points, global_points.(_i+1).1 - _.1 );
|
durations = map(global_points, global_points:(_i+1):1 - _:1 );
|
||||||
put(durations, -1, last_section_duration);
|
durations:(-1) = last_section_duration;
|
||||||
loop(times,
|
loop(times,
|
||||||
loop( length(positions),
|
loop( length(positions),
|
||||||
__add_path_segment(positions._, durations._, modes._)
|
__add_path_segment(positions:_, durations:_, modes:_)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
str('Add %d points %d times', length(positions), times)
|
str('Add %d points %d times', length(positions), times)
|
||||||
@@ -91,13 +91,13 @@ speed(percentage) ->
|
|||||||
exit('path speed can only be speed, or slowed down 4 times. Recall command for larger changes')
|
exit('path speed can only be speed, or slowed down 4 times. Recall command for larger changes')
|
||||||
);
|
);
|
||||||
ratio = percentage/100;
|
ratio = percentage/100;
|
||||||
previous_path_length = global_points.(-1).1;
|
previous_path_length = global_points:(-1):1;
|
||||||
for(global_points, put(_, 1, _.1*ratio ) );
|
for(global_points, _:1 = _:1*ratio );
|
||||||
undef('global_path_precalculated');
|
undef('global_path_precalculated');
|
||||||
str('path %s from %d to %d ticks',
|
str('path %s from %d to %d ticks',
|
||||||
if(ratio<1,'shortened','extended'),
|
if(ratio<1,'shortened','extended'),
|
||||||
previous_path_length,
|
previous_path_length,
|
||||||
global_points.(-1).1
|
global_points:(-1):1
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
select_interpolation(method) ->
|
select_interpolation(method) ->
|
||||||
@@ -132,14 +132,14 @@ __assert_valid_for_motion() ->
|
|||||||
);
|
);
|
||||||
__get_path_at(segment, start, index) ->
|
__get_path_at(segment, start, index) ->
|
||||||
(
|
(
|
||||||
v = global_path_precalculated.(start+index);
|
v = global_path_precalculated:(start+index);
|
||||||
if(v == null,
|
if(v == null,
|
||||||
v = __find_position_for_point(segment, index);
|
v = __find_position_for_point(segment, index);
|
||||||
put(global_path_precalculated, start+index, v)
|
global_path_precalculated:(start+index) = v
|
||||||
);
|
);
|
||||||
v
|
v
|
||||||
);
|
);
|
||||||
__invalidate_points_cache() -> global_path_precalculated = map(range(global_points. (-1) . 1), null);
|
__invalidate_points_cache() -> global_path_precalculated = map(range(global_points:(-1):1), null);
|
||||||
show() ->
|
show() ->
|
||||||
(
|
(
|
||||||
loop(100,
|
loop(100,
|
||||||
@@ -160,8 +160,8 @@ play(fps) ->
|
|||||||
point = 0;
|
point = 0;
|
||||||
loop( length(global_points)-1,
|
loop( length(global_points)-1,
|
||||||
segment = _;
|
segment = _;
|
||||||
start = global_points.segment.1;
|
start = global_points:segment:1;
|
||||||
end = global_points.(segment+1).1;
|
end = global_points:(segment+1):1;
|
||||||
loop(end-start,
|
loop(end-start,
|
||||||
v = __get_path_at(segment, start, _);
|
v = __get_path_at(segment, start, _);
|
||||||
modify(p, 'location', v);
|
modify(p, 'location', v);
|
||||||
@@ -182,8 +182,8 @@ _show_path_tick(particle_type, total) ->
|
|||||||
__prepare_path_if_needed();
|
__prepare_path_if_needed();
|
||||||
loop(total,
|
loop(total,
|
||||||
segment = floor(rand(length(global_points)-1));
|
segment = floor(rand(length(global_points)-1));
|
||||||
start = global_points.segment.1;
|
start = global_points:segment:1;
|
||||||
end = global_points.(segment+1).1;
|
end = global_points:(segment+1):1;
|
||||||
index = floor(rand(end-start));
|
index = floor(rand(end-start));
|
||||||
l(x, y, z) = slice(__get_path_at(segment, start, index), 0, 3);
|
l(x, y, z) = slice(__get_path_at(segment, start, index), 0, 3);
|
||||||
particle(particle_type, x, y, z, 1, 0, 0)
|
particle(particle_type, x, y, z, 1, 0, 0)
|
||||||
@@ -196,8 +196,8 @@ __prepare_path_if_needed_generic() ->
|
|||||||
);
|
);
|
||||||
__find_position_for_linear(segment, point) ->
|
__find_position_for_linear(segment, point) ->
|
||||||
(
|
(
|
||||||
l(va, start, mode_a) = global_points.segment;
|
l(va, start, mode_a) = global_points:segment;
|
||||||
l(vb, end, mode_b) = global_points.(segment+1);
|
l(vb, end, mode_b) = global_points:(segment+1);
|
||||||
section = end-start;
|
section = end-start;
|
||||||
dt = point/section;
|
dt = point/section;
|
||||||
dt*vb+(1-dt)*va
|
dt*vb+(1-dt)*va
|
||||||
@@ -209,15 +209,15 @@ __find_position_for_gauss(from_index, point) ->
|
|||||||
(
|
(
|
||||||
dev = global_interpol_option;
|
dev = global_interpol_option;
|
||||||
components = l();
|
components = l();
|
||||||
path_point = global_points.from_index.1;
|
path_point = global_points:from_index:1;
|
||||||
|
|
||||||
try(
|
try(
|
||||||
for(range(from_index+1, length(global_points)),
|
for(range(from_index+1, length(global_points)),
|
||||||
l(v,ptime,mode) = global_points._;
|
l(v,ptime,mode) = global_points:_;
|
||||||
dev = if (global_interpol_option > 0, global_interpol_option,
|
dev = if (global_interpol_option > 0, global_interpol_option,
|
||||||
devs = l();
|
devs = l();
|
||||||
if (_+1 < length(global_points), devs += global_points.(_+1).1-ptime);
|
if (_+1 < length(global_points), devs += global_points:(_+1):1-ptime);
|
||||||
if (_-1 >= 0, devs += ptime-global_points.(_-1).1);
|
if (_-1 >= 0, devs += ptime-global_points:(_-1):1);
|
||||||
0.6*reduce(devs, _a+_, 0)/length(devs)
|
0.6*reduce(devs, _a+_, 0)/length(devs)
|
||||||
);
|
);
|
||||||
impact = __norm_prob(path_point+point, ptime, dev);
|
impact = __norm_prob(path_point+point, ptime, dev);
|
||||||
@@ -228,11 +228,11 @@ __find_position_for_gauss(from_index, point) ->
|
|||||||
);
|
);
|
||||||
try(
|
try(
|
||||||
for(range(from_index, -1, -1),
|
for(range(from_index, -1, -1),
|
||||||
l(v,ptime,mode) = global_points._;
|
l(v,ptime,mode) = global_points:_;
|
||||||
dev = if (global_interpol_option > 0, global_interpol_option,
|
dev = if (global_interpol_option > 0, global_interpol_option,
|
||||||
devs = l();
|
devs = l();
|
||||||
if (_+1 < length(global_points), devs += global_points.(_+1).1-ptime);
|
if (_+1 < length(global_points), devs += global_points:(_+1):1-ptime);
|
||||||
if (_-1 >= 0, devs += ptime-global_points.(_-1).1);
|
if (_-1 >= 0, devs += ptime-global_points:(_-1):1);
|
||||||
0.6*reduce(devs, _a+_, 0)/length(devs)
|
0.6*reduce(devs, _a+_, 0)/length(devs)
|
||||||
);
|
);
|
||||||
impact = __norm_prob(path_point+point, ptime, dev);
|
impact = __norm_prob(path_point+point, ptime, dev);
|
||||||
@@ -242,5 +242,5 @@ __find_position_for_gauss(from_index, point) ->
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
total = rtotal+ltotal;
|
total = rtotal+ltotal;
|
||||||
reduce(components, _a+_.0*(_.1/total), l(0,0,0,0,0))
|
reduce(components, _a+_:0*(_:1/total), l(0,0,0,0,0))
|
||||||
)
|
)
|
||||||
@@ -67,6 +67,7 @@
|
|||||||
"PlayerEntity_parrotMixin",
|
"PlayerEntity_parrotMixin",
|
||||||
"SaplingBlockMixin",
|
"SaplingBlockMixin",
|
||||||
"EntityMixin",
|
"EntityMixin",
|
||||||
|
"FlatChunkGeneratorMixin",
|
||||||
|
|
||||||
"BiomeArray_getBiomeArrayMixin",
|
"BiomeArray_getBiomeArrayMixin",
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user