Merge branch 'master' into 1.15

# Conflicts:
#	src/main/java/carpet/script/CarpetExpression.java
This commit is contained in:
gnembon committed 2019-10-13 02:55:19 -03:00
commit 7fae5c92cf
20 files changed
+553 -138

No files matched your search

+1
View File
@@ -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();
}
} }
} }
+1
View File
@@ -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<>();
+151 -42
View File
@@ -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) =&gt; 5 * get(l(range(10)), 5) =&gt; 5
* get(l(range(10)), -1) =&gt; 9 * get(l(range(10)), -1) =&gt; 9
* get(l(range(10)), 10) =&gt; 0 * get(l(range(10)), 10) =&gt; 0
* l(range(10)).93 =&gt; 3 * l(range(10)):93 =&gt; 3
* *
* get(player() ~ 'nbt', 'Health') =&gt; 20 // inefficient way to get player health, use player() ~ 'health' instead * get(player() ~ 'nbt', 'Health') =&gt; 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;
}); });
} }
+71 -5
View File
@@ -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
+1 -7
View File
@@ -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))
) )
+1
View File
@@ -67,6 +67,7 @@
"PlayerEntity_parrotMixin", "PlayerEntity_parrotMixin",
"SaplingBlockMixin", "SaplingBlockMixin",
"EntityMixin", "EntityMixin",
"FlatChunkGeneratorMixin",
"BiomeArray_getBiomeArrayMixin", "BiomeArray_getBiomeArrayMixin",