Merge branch 'master' into future

# Conflicts:
#	gradle.properties
#	src/main/java/carpet/script/annotation/AnnotationParser.java
#	src/main/java/carpet/script/utils/BiomeInfo.java
#	src/main/resources/fabric.mod.json
This commit is contained in:
gnembon committed 2022-01-11 23:44:52 +01:00
commit 529a5b358d
38 files changed
+247 -381

No files matched your search

@@ -91,7 +91,7 @@ public class CarpetExpression
public Value scriptRunCommand(ScriptHost host, BlockPos pos)
{
if (CarpetServer.scriptServer.stopAll)
throw new CarpetExpressionException("SCRIPTING PAUSED", null);
throw new CarpetExpressionException("SCRIPTING PAUSED (unpause with /script resume)", null);
try
{
Context context = new CarpetContext(host, source, origin).
@@ -13,6 +13,7 @@ import carpet.script.exception.ExpressionException;
import carpet.script.exception.IntegrityException;
import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.InvalidCallbackException;
import carpet.script.exception.LoadException;
import carpet.script.utils.AppStoreManager;
import carpet.script.value.EntityValue;
import carpet.script.value.FunctionValue;
@@ -37,6 +38,7 @@ import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.SemanticVersion;
import net.fabricmc.loader.api.Version;
import net.fabricmc.loader.api.VersionParsingException;
import net.fabricmc.loader.api.metadata.version.VersionPredicate;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.nbt.NbtElement;
@@ -60,7 +62,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -119,8 +120,7 @@ public class CarpetScriptHost extends ScriptHost
String code = module.getCode();
if (code == null)
{
Messenger.m(source, "r Unable to load "+module.getName()+" app - code not found");
return null;
throw new LoadException("Code not found");
}
host.setChatErrorSnooper(source);
CarpetExpression ex = new CarpetExpression(host.main, code, source, new BlockPos(0, 0, 0));
@@ -131,13 +131,12 @@ public class CarpetScriptHost extends ScriptHost
catch (CarpetExpressionException e)
{
host.handleErrorWithStack("Error while evaluating expression", e);
host.resetErrorSnooper();
return null;
throw new LoadException();
}
catch (ArithmeticException ae)
catch (ArithmeticException ae) // is this branch ever reached? Seems like arithmetic exceptions are converted to CEEs earlier
{
host.handleErrorWithStack("Math doesn't compute", ae);
return null;
throw new LoadException();
}
catch (StackOverflowError soe)
{
@@ -314,7 +313,7 @@ public class CarpetScriptHost extends ScriptHost
{
Value reqResult = callNow((FunctionValue) loadRequirements, Collections.emptyList());
if (reqResult.getBoolean()) // != false or null
throw new InternalExpressionException(reqResult.getString());
throw new LoadException(reqResult.getString());
}
else
{
@@ -422,20 +421,6 @@ public class CarpetScriptHost extends ScriptHost
return addLegacyCommand(notifier);
}
// Prefixes based on FLoader's SemanticVersionPredicateParser's class prefixes under Apache 2.0, since that's not public API
private static final Map<String, BiPredicate<SemanticVersion, SemanticVersion>> VERSION_PREFIXES = new HashMap<String, BiPredicate<SemanticVersion, SemanticVersion>>() {{
put(">=", (target, source) -> source.compareTo(target) >= 0);
put("<=", (target, source) -> source.compareTo(target) <= 0);
put(">", (target, source) -> source.compareTo(target) > 0);
put("<", (target, source) -> source.compareTo(target) < 0);
put("=", (target, source) -> source.compareTo(target) == 0);
put("~", (target, source) -> source.compareTo(target) >= 0
&& source.getVersionComponent(0) == target.getVersionComponent(0)
&& source.getVersionComponent(1) == target.getVersionComponent(1));
put("^", (target, source) -> source.compareTo(target) >= 0
&& source.getVersionComponent(0) == target.getVersionComponent(0));
}};
public void checkModVersionRequirements(Value reqs) {
if (reqs == null)
return;
@@ -446,58 +431,25 @@ public class CarpetScriptHost extends ScriptHost
Map<Value, Value> requirements = ((MapValue)reqs).getMap();
for (Entry<Value, Value> requirement : requirements.entrySet())
{
boolean successful = false;
String requiredModId = requirement.getKey().getString();
String requirementString = requirement.getValue().getString();
String stringPredicate = requirement.getValue().getString();
VersionPredicate predicate;
try {
predicate = VersionPredicate.parse(stringPredicate);
} catch (VersionParsingException e) {
throw new InternalExpressionException("Failed to parse version conditions for '" + requiredModId + "' in 'requires': " + e.getMessage());
}
ModContainer mod = FabricLoader.getInstance().getModContainer(requiredModId).orElse(null);
if (mod != null)
{
if (requirementString.equals("*"))
continue;
Version presentVersion = mod.getMetadata().getVersion();
BiPredicate<SemanticVersion, SemanticVersion> tester = null;
String remainingRequirementString = requirementString;
for (Entry<String, BiPredicate<SemanticVersion, SemanticVersion>> s : VERSION_PREFIXES.entrySet())
{
if (requirementString.startsWith(s.getKey()))
{
tester = s.getValue();
remainingRequirementString = requirementString.substring(s.getKey().length());
}
}
if (tester == null)
tester = VERSION_PREFIXES.get("=");
if (presentVersion instanceof SemanticVersion)
{
SemanticVersion requiredVersion = null;
try {
requiredVersion = SemanticVersion.parse(remainingRequirementString);
}
catch (VersionParsingException e)
{
throw new InternalExpressionException("Failed to parse semantic version for '" + requiredModId + "' in 'requires': " + e.getMessage());
}
if (tester.test(requiredVersion, (SemanticVersion) presentVersion))
successful = true;
}
else
{
if (FabricLoader.getInstance().isDevelopmentEnvironment())
successful = true; // Autoversioning breaks semver in dev (loads as ${version})
else
{
if (!(tester == VERSION_PREFIXES.get("=")))
throw new InternalExpressionException("Mod '"+requiredModId+"' doesn't use semversion, thus can only check version equality");
if (presentVersion.getFriendlyString().equals(remainingRequirementString))
successful = true;
}
if (predicate.test(presentVersion) || (FabricLoader.getInstance().isDevelopmentEnvironment() && !(presentVersion instanceof SemanticVersion)))
{ // in a dev env, mod version is usually replaced with ${version}, and that isn't semantic
continue;
}
}
if (!successful)
{
throw new InternalExpressionException(getName()+" requires " + requiredModId + " version " + requirementString + " in order to load");
}
throw new LoadException(String.format("%s requires a version of mod '%s' matching '%s', which is missing!", getName(), requiredModId, stringPredicate));
}
}
@@ -732,10 +684,10 @@ public class CarpetScriptHost extends ScriptHost
public Value callLegacy(ServerCommandSource source, String call, List<Integer> coords, String arg)
{
if (CarpetServer.scriptServer.stopAll)
throw new CarpetExpressionException("SCARPET PAUSED", null);
throw new CarpetExpressionException("SCARPET PAUSED (unpause with /script resume)", null);
FunctionValue function = getFunction(call);
if (function == null)
throw new CarpetExpressionException("UNDEFINED", null);
throw new CarpetExpressionException("Couldn't find function '" + call + "' in app '" + this.getName() + "'", null);
List<LazyValue> argv = new ArrayList<>();
if (coords != null)
for (Integer i: coords)
@@ -832,7 +784,7 @@ public class CarpetScriptHost extends ScriptHost
public Value call(ServerCommandSource source, FunctionValue function, List<Value> argv)
{
if (CarpetServer.scriptServer.stopAll)
throw new CarpetExpressionException("SCARPET PAUSED", null);
throw new CarpetExpressionException("SCARPET PAUSED (unpause with /script resume)", null);
List<String> args = function.getArguments();
if (argv.size() != args.size())
@@ -13,6 +13,7 @@ import carpet.CarpetServer;
import carpet.script.bundled.FileModule;
import carpet.script.bundled.Module;
import carpet.script.exception.ExpressionException;
import carpet.script.exception.LoadException;
import carpet.script.language.Arithmetic;
import carpet.script.language.ControlFlow;
import carpet.script.language.DataStructures;
@@ -256,10 +257,14 @@ public class CarpetScriptServer
Messenger.m(source, "r Failed to add "+name+" app");
return false;
}
CarpetScriptHost newHost = CarpetScriptHost.create(this, module, perPlayer, source, commandValidator, isRuleApp, installer);
if (newHost == null)
CarpetScriptHost newHost;
try
{
Messenger.m(source, "r Failed to add "+name+" app");
newHost = CarpetScriptHost.create(this, module, perPlayer, source, commandValidator, isRuleApp, installer);
}
catch (LoadException e)
{
Messenger.m(source, "r Failed to add " + name + " app" + (e.getMessage() == null ? "" : ": " + e.getMessage()));
return false;
}
// config needs to be read as we load the app since some events use that info
+7 -4
View File
@@ -481,9 +481,9 @@ public class Expression
}
public void addLazyFunction(String name, int num_params, TriFunction<Context, Context.Type, List<LazyValue>, LazyValue> fun)
public void addLazyFunction(String name, int numParams, TriFunction<Context, Context.Type, List<LazyValue>, LazyValue> fun)
{
functions.put(name, new AbstractLazyFunction(num_params, name)
functions.put(name, new AbstractLazyFunction(numParams, name)
{
@Override
public boolean pure() {
@@ -499,8 +499,11 @@ public class Expression
public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List<LazyValue> lazyParams)
{
ILazyFunction.checkInterrupts();
if (num_params >= 0 && lazyParams.size() != num_params)
throw new InternalExpressionException("'"+name+"' requires "+num_params+" parameters, "+lazyParams.size()+" provided.");
if (numParams >= 0 && lazyParams.size() != numParams)
{
String error = "Function '"+name+"' requires "+numParams+" arguments, got "+lazyParams.size()+". ";
throw new InternalExpressionException(error + (fun instanceof Fluff.UsageProvider up ? up.getUsage() : ""));
}
try
{
+2
View File
@@ -30,6 +30,8 @@ public abstract class Fluff
@FunctionalInterface
public interface SexFunction<A, B, C, D, E, F, R> { R apply(A a, B b, C c, D d, E e, F f);}
public interface UsageProvider { String getUsage();}
public interface EvalNode
{
/**
@@ -21,6 +21,7 @@ import carpet.script.Context;
import carpet.script.Expression;
import carpet.script.Fluff.AbstractLazyFunction;
import carpet.script.Fluff.TriFunction;
import carpet.script.Fluff.UsageProvider;
import carpet.script.exception.InternalExpressionException;
import carpet.script.LazyValue;
import carpet.script.value.Value;
@@ -73,6 +74,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
*/
public final class AnnotationParser
{
static final int UNDEFINED_PARAMS = -2;
private static final List<ParsedFunction> functionList = new ArrayList<>();
/**
@@ -90,8 +92,8 @@ public final class AnnotationParser
* {@link InternalExpressionException}).
* Basically, it's fine as long as you don't add a {@code throws} declaration to your methods.</li>
* <li>Varargs (or effectively varargs) annotated methods must explicitly declare a maximum number of parameters to ingest in the {@link ScarpetFunction}
* annotation. They can still declare an unlimited amount by setting that maximum to {@code -1}. "Effectively varargs" means a function that has
* a parameter using/requiring a {@link ValueConverter} that has declared {@link ValueConverter#consumesVariableArgs()}.</li>
* annotation. They can still declare an unlimited amount by setting that maximum to {@link ScarpetFunction#UNLIMITED_PARAMS}. "Effectively varargs"
* means a function that has at least a parameter requiring a {@link ValueConverter} that has declared {@link ValueConverter#consumesVariableArgs()}.</li>
* <li>Annotated methods must not have a parameter with generics as the varargs parameter. This is just because it was painful for me (altrisi) and
* didn't want to support it. Those will crash with a {@code ClassCastException}</li>
* </ul>
@@ -141,7 +143,7 @@ public final class AnnotationParser
expr.addLazyFunction(function.name, function.scarpetParamCount, function);
}
private static class ParsedFunction implements TriFunction<Context, Context.Type, List<LazyValue>, LazyValue>
private static class ParsedFunction implements TriFunction<Context, Context.Type, List<LazyValue>, LazyValue>, UsageProvider
{
private final String name;
private final boolean isMethodVarArgs;
@@ -186,10 +188,10 @@ public final class AnnotationParser
if (this.isEffectivelyVarArgs)
{
maxParams = method.getAnnotation(ScarpetFunction.class).maxParams();
if (maxParams == -2)
throw new IllegalArgumentException("No maximum number of params specified for " + name + ", use -1 for unlimited. "
if (maxParams == UNDEFINED_PARAMS)
throw new IllegalArgumentException("No maximum number of params specified for " + name + ", use ScarpetFunction.UNLIMITED_PARAMS for unlimited. "
+ "Provided in " + instance.getClass());
if (maxParams == -1)
if (maxParams == ScarpetFunction.UNLIMITED_PARAMS)
maxParams = Integer.MAX_VALUE;
if (maxParams < this.minParams)
throw new IllegalArgumentException("Provided maximum number of params for " + name + " is smaller than method's param count."
@@ -293,7 +295,8 @@ public final class AnnotationParser
return params;
}
private String getUsage()
@Override
public String getUsage()
{
// Possibility: More descriptive messages using param.getName()? Would need changing gradle setup to keep those
StringBuilder builder = new StringBuilder("Usage: '");
@@ -51,6 +51,11 @@ import carpet.script.value.Value;
@Retention(RUNTIME)
public @interface ScarpetFunction
{
/**
* <p>Used to define that this {@link ScarpetFunction} can accept an unlimited number of parameters</p>
*/
public static final int UNLIMITED_PARAMS = -1;
/**
* <p>If the function can accept a variable number of parameters, either by declaring its last parameter as a varargs parameter or by having one
* of their parameters use a converter that consumes a variable number of arguments, this must define the maximum number of parameters this
@@ -65,11 +70,11 @@ public @interface ScarpetFunction
* consider that those can take either a single triple of values or 3 independent values, that would be counted in the maximum number of
* parameters.</p>
*
* <p>Use -1 to specify an unlimited number of parameters.</p>
* <p>Use {@link ScarpetFunction#UNLIMITED_PARAMS} to allow an unlimited number of parameters.</p>
*
* @return The maximum number of parameters this function can accept
*/
int maxParams() default -2;
int maxParams() default AnnotationParser.UNDEFINED_PARAMS;
/**
* <p>Defines the Context Type that will be used when evaluating arguments to annotated methods.</p>
@@ -162,13 +162,13 @@ public interface ValueConverter<R>
* constraints as {@link #convert(Value)}</p>
* @param valueIterator An {@link Iterator} holding the {@link Value} to convert in next position
* @param context The {@link Context} this function has been called with. This was used when this passed lazy values instead in order to
* evaluate, now it's used to get the context. It is now ignored by the default implementation
* @param theLazyT The {@code t} that the original function was called with. It is ignored by the default implementation.
* evaluate, now it's used to get the context
* @param contextType The {@link Context.Type} that the original function was called with
* @return The next {@link Value} (s) converted to the type {@code <R>} of this {@link ValueConverter}
* @implNote This method's default implementation runs the {@link #convert(Value)} function in the next {@link Value} ignoring {@link Context} and
* {@code theLazyT}.
*/
default public R checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type theLazyT)
default public R checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type contextType)
{
if (!valueIterator.hasNext())
return null;
@@ -676,7 +676,7 @@ public class Auxiliary {
expression.addContextFunction("last_tick_times", -1, (c, t, lv) ->
{
c.host.issueDeprecation("last_tick_times()");
return SystemInfo.get("last_tick_times", (CarpetContext)c);
return SystemInfo.get("server_last_tick_times", (CarpetContext)c);
});
@@ -736,6 +736,7 @@ public class Auxiliary {
return Value.TRUE;
});
// Should this be deprecated for system_info('source_dimension')?
expression.addContextFunction("current_dimension", 0, (c, t, lv) ->
ValueConversions.of( ((CarpetContext)c).s.getWorld()));
+32 -44
View File
@@ -3,6 +3,7 @@ package carpet.script.api;
import carpet.script.CarpetContext;
import carpet.script.CarpetEventServer;
import carpet.script.CarpetScriptHost;
import carpet.script.Context;
import carpet.script.Expression;
import carpet.script.argument.FunctionArgument;
import carpet.script.argument.Vector3Argument;
@@ -36,9 +37,20 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Entities {
private static ListValue getPlayersFromWorldMatching(Context c, Predicate<ServerPlayerEntity> condition) {
List<Value> ret = new ArrayList<>();
for (ServerPlayerEntity player: ((CarpetContext) c).s.getWorld().getPlayers()) {
if (condition.test(player)) {
ret.add(new EntityValue(player));
}
}
return ListValue.wrap(ret);
}
public static void apply(Expression expression)
{
expression.addContextFunction("player", -1, (c, t, lv) ->
@@ -58,50 +70,26 @@ public class Entities {
return EntityValue.of(closestPlayer);
}
String playerName = lv.get(0).getString();
Value retval = Value.NULL;
if ("all".equalsIgnoreCase(playerName))
{
retval = ListValue.wrap(
((CarpetContext)c).s.getServer().getPlayerManager().getPlayerList().
stream().map(EntityValue::new).collect(Collectors.toList()));
}
else if ("*".equalsIgnoreCase(playerName))
{
retval = ListValue.wrap(
((CarpetContext)c).s.getWorld().getPlayers().
stream().map(EntityValue::new).collect(Collectors.toList()));
}
else if ("survival".equalsIgnoreCase(playerName))
{
retval = ListValue.wrap(
((CarpetContext)c).s.getWorld().getPlayers((p) -> p.interactionManager.isSurvivalLike()).
stream().map(EntityValue::new).collect(Collectors.toList()));
}
else if ("creative".equalsIgnoreCase(playerName))
{
retval = ListValue.wrap(
((CarpetContext)c).s.getWorld().getPlayers(PlayerEntity::isCreative).
stream().map(EntityValue::new).collect(Collectors.toList()));
}
else if ("spectating".equalsIgnoreCase(playerName))
{
retval = ListValue.wrap(
((CarpetContext)c).s.getWorld().getPlayers(PlayerEntity::isSpectator).
stream().map(EntityValue::new).collect(Collectors.toList()));
}
else if ("!spectating".equalsIgnoreCase(playerName))
{
retval = ListValue.wrap(
((CarpetContext)c).s.getWorld().getPlayers((p) -> !p.isSpectator()).
stream().map(EntityValue::new).collect(Collectors.toList()));
}
else
{
ServerPlayerEntity player = ((CarpetContext) c).s.getServer().getPlayerManager().getPlayer(playerName);
if (player != null)
retval = new EntityValue(player);
}
return retval;
return switch (playerName) {
case "all" -> {
List<Value> ret = new ArrayList<>();
for (ServerPlayerEntity player: ((CarpetContext)c).s.getServer().getPlayerManager().getPlayerList())
ret.add(new EntityValue(player));
yield ListValue.wrap(ret);
}
case "*" -> getPlayersFromWorldMatching(c, p -> true);
case "survival" -> getPlayersFromWorldMatching(c, p -> p.interactionManager.isSurvivalLike());
case "creative" -> getPlayersFromWorldMatching(c, PlayerEntity::isCreative);
case "spectating" -> getPlayersFromWorldMatching(c, PlayerEntity::isSpectator);
case "!spectating" -> getPlayersFromWorldMatching(c, p -> !p.isSpectator());
default -> {
ServerPlayerEntity player = ((CarpetContext) c).s.getServer().getPlayerManager().getPlayer(playerName);
if (player != null) {
yield new EntityValue(player);
}
yield Value.NULL;
}
};
});
expression.addContextFunction("spawn", -1, (c, t, lv) ->
@@ -0,0 +1,19 @@
package carpet.script.exception;
/**
* A Scarpet exception that indicates that load of the app has failed.
*
* Goes up the stack to the point of app load and gets caught there, preventing the app from loading with
* the given message.
*
*/
public class LoadException extends RuntimeException implements ResolvedException {
public LoadException() {
super();
}
public LoadException(String message) {
super(message);
}
}
@@ -8,9 +8,7 @@ import carpet.script.value.NumericValue;
import carpet.script.value.StringValue;
import carpet.script.value.Value;
import carpet.script.value.ValueConversions;
import net.minecraft.client.color.world.FoliageColors;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.feature.ConfiguredFeature;
@@ -27,11 +25,11 @@ public class BiomeInfo
//put("under_material", (w, b) -> new BlockValue( b.getGenerationSettings().getSurfaceConfig().getUnderMaterial(), null, null));
put("category", (w, b) -> StringValue.of(b.getCategory().getName()));
put("temperature", (w, b) -> NumericValue.of(b.getTemperature()));
put("fog_color", (w, b) -> ValueConversions.ofRGB(((BiomeEffectsInterface)b.getEffects()).getCMFogColor()));
put("foliage_color", (w, b) -> ValueConversions.ofRGB(((BiomeEffectsInterface)b.getEffects()).getCMFoliageColor().orElse(4764952))); // client Biome.getDefaultFoliageColor
put("sky_color", (w, b) -> ValueConversions.ofRGB(((BiomeEffectsInterface)b.getEffects()).getCMSkyColor()));
put("water_color", (w, b) -> ValueConversions.ofRGB(((BiomeEffectsInterface)b.getEffects()).getCMWaterColor()));
put("water_fog_color", (w, b) -> ValueConversions.ofRGB(((BiomeEffectsInterface)b.getEffects()).getCMWaterFogColor()));
put("fog_color", (w, b) -> ValueConversions.ofRGB(b.getEffects().getFogColor()));
put("foliage_color", (w, b) -> ValueConversions.ofRGB(b.getEffects().getFoliageColor().orElse(4764952))); // client Biome.getDefaultFoliageColor
put("sky_color", (w, b) -> ValueConversions.ofRGB(b.getEffects().getSkyColor()));
put("water_color", (w, b) -> ValueConversions.ofRGB(b.getEffects().getWaterColor()));
put("water_fog_color", (w, b) -> ValueConversions.ofRGB(b.getEffects().getWaterFogColor()));
put("humidity", (w, b) -> NumericValue.of(b.getDownfall()));
put("precipitation", (w, b) -> StringValue.of(b.getPrecipitation().getName()));
//put("depth", (w, b) -> NumericValue.of(b.getDepth()));
@@ -5,6 +5,7 @@ import carpet.CarpetSettings;
import carpet.script.CarpetContext;
import carpet.script.CarpetScriptHost;
import carpet.script.value.BooleanValue;
import carpet.script.value.EntityValue;
import carpet.script.value.ListValue;
import carpet.script.value.MapValue;
import carpet.script.value.NumericValue;
@@ -17,11 +18,9 @@ import com.sun.management.OperatingSystemMXBean;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.SharedConstants;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.WorldSavePath;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.util.math.Vec2f;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import net.minecraft.world.WorldProperties;
import net.minecraft.world.border.WorldBorder;
@@ -74,7 +73,9 @@ public class SystemInfo {
return ListValue.fromTriple(worldBorder.getCenterX(), 0, worldBorder.getCenterZ());
});
put("world_size", c-> new NumericValue( c.s.getWorld().getWorldBorder().getMaxRadius()));
put("world_size", c -> new NumericValue(c.s.getWorld().getWorldBorder().getSize() / 2));
put("world_max_size", c-> new NumericValue( c.s.getWorld().getWorldBorder().getMaxRadius()));
put("world_time", c -> new NumericValue(c.s.getWorld().getTime()));
@@ -199,6 +200,15 @@ public class SystemInfo {
});
return MapValue.wrap(rules);
});
put("source_entity", c -> EntityValue.of(c.s.getEntity()));
put("source_position", c -> ValueConversions.of(c.s.getPosition()));
put("source_dimension", c -> ValueConversions.of(c.s.getWorld()));
put("source_rotation", c -> {
Vec2f rotation = c.s.getRotation();
return ListValue.of(new NumericValue(rotation.x), new NumericValue(rotation.y));
});
put("scarpet_version", c -> StringValue.of(CarpetSettings.carpetVersion));
}};
@@ -1,10 +1,8 @@
package carpet.script.value;
import carpet.fakes.BrainInterface;
import carpet.fakes.EntityInterface;
import carpet.fakes.ItemEntityInterface;
import carpet.fakes.LivingEntityInterface;
import carpet.fakes.MemoryInterface;
import carpet.fakes.MobEntityInterface;
import carpet.fakes.ServerPlayerEntityInterface;
import carpet.fakes.ServerPlayerInteractionManagerInterface;
@@ -633,11 +631,11 @@ public class EntityValue extends Value
if (e instanceof LivingEntity livingEntity)
{
Brain<?> brain = livingEntity.getBrain();
Map<MemoryModuleType<?>, Optional<? extends Memory<?>>> memories = ((BrainInterface)brain).getMobMemories();
Map<MemoryModuleType<?>, Optional<? extends Memory<?>>> memories = brain.getMemories();
Optional<? extends Memory<?>> optmemory = memories.get(moduleType);
if (optmemory==null || !optmemory.isPresent()) return Value.NULL;
Memory<?> memory = optmemory.get();
return ValueConversions.fromTimedMemory(e, ((MemoryInterface)memory).getScarpetExpiry(), memory.getValue());
return ValueConversions.fromTimedMemory(e, memory.getExpiry(), memory.getValue());
}
return Value.NULL;
});
@@ -1584,7 +1582,7 @@ public class EntityValue extends Value
});
put("absorption", (e, v) -> {
if (e instanceof PlayerEntity) ((PlayerEntity) e).setAbsorptionAmount((float) NumericValue.asNumber(v, "absorbtion").getLong());
if (e instanceof PlayerEntity) ((PlayerEntity) e).setAbsorptionAmount(NumericValue.asNumber(v, "absorbtion").getFloat());
});
put("add_xp", (e, v) -> {
@@ -19,18 +19,29 @@ public class ThreadValue extends Value
private final long id;
private static long sequence = 0L;
public ThreadValue(CompletableFuture<Value> taskFuture)
{
this.taskFuture = taskFuture;
this.id = sequence++;
}
public ThreadValue(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List<Value> args)
{
id = sequence++;
this(getCompletableFutureFromFunction(pool, function, expr, token, ctx, args));
Thread.yield();
}
public static CompletableFuture<Value> getCompletableFutureFromFunction(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List<Value> args)
{
ExecutorService executor = ctx.host.getExecutor(pool);
if (executor == null)
{
// app is shutting down - no more threads can be spawned.
taskFuture = CompletableFuture.completedFuture(Value.NULL);
return CompletableFuture.completedFuture(Value.NULL);
}
else
{
taskFuture = CompletableFuture.supplyAsync(
return CompletableFuture.supplyAsync(
() ->
{
try
@@ -52,7 +63,6 @@ public class ThreadValue extends Value
ctx.host.getExecutor(pool)
);
}
Thread.yield();
}
@Override