Merge branch 'master' into 1.17
This commit is contained in:
commit
0bacbcc2f5
18 files changed
+669
-349
No files matched your search
@@ -14,6 +14,7 @@ import carpet.script.value.Value;
|
||||
import carpet.script.value.ValueConversions;
|
||||
import carpet.settings.ParsedRule;
|
||||
import carpet.utils.Messenger;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
@@ -47,8 +48,9 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -65,59 +67,84 @@ public class CarpetEventServer
|
||||
public static class Callback
|
||||
{
|
||||
public final String host;
|
||||
public final String optionalTarget;
|
||||
public final FunctionValue function;
|
||||
public final List<Value> parametrizedArgs;
|
||||
|
||||
|
||||
public Callback(String host, FunctionValue function, List<Value> parametrizedArgs)
|
||||
public Callback(String host, String target, FunctionValue function, List<Value> parametrizedArgs)
|
||||
{
|
||||
this.host = host;
|
||||
this.function = function;
|
||||
this.optionalTarget = target;
|
||||
this.parametrizedArgs = parametrizedArgs==null?NOARGS:parametrizedArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used also in entity events
|
||||
* @param asSource - entity command source
|
||||
* @param sender - entity command source
|
||||
* @param runtimeArgs = options
|
||||
*/
|
||||
public boolean execute(ServerCommandSource asSource, List<Value> runtimeArgs)
|
||||
public boolean execute(ServerCommandSource sender, List<Value> runtimeArgs)
|
||||
{
|
||||
if (this.parametrizedArgs.isEmpty())
|
||||
return CarpetServer.scriptServer.runas(
|
||||
asSource.withLevel(CarpetSettings.runPermissionLevel),
|
||||
host, function, runtimeArgs);
|
||||
else
|
||||
if (!this.parametrizedArgs.isEmpty())
|
||||
{
|
||||
List<Value> combinedArgs = new ArrayList<>(runtimeArgs);
|
||||
combinedArgs.addAll(this.parametrizedArgs);
|
||||
return CarpetServer.scriptServer.runas(
|
||||
asSource.withLevel(CarpetSettings.runPermissionLevel),
|
||||
host, function, combinedArgs);
|
||||
runtimeArgs = new ArrayList<>(runtimeArgs);
|
||||
runtimeArgs.addAll(this.parametrizedArgs);
|
||||
}
|
||||
return CarpetServer.scriptServer.runEventCall(
|
||||
sender.withLevel(CarpetSettings.runPermissionLevel),
|
||||
host, optionalTarget, function, runtimeArgs
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used also in entity events
|
||||
* @param recipient - optional target player argument
|
||||
* @param sender - sender of the signal
|
||||
* @param optionalRecipient - optional target player argument
|
||||
* @param runtimeArgs = options
|
||||
*/
|
||||
public Boolean targetPlayer(ServerPlayerEntity recipient, List<Value> runtimeArgs)
|
||||
public int signal(ServerCommandSource sender, ServerPlayerEntity optionalRecipient, List<Value> runtimeArgs)
|
||||
{
|
||||
// recipent of the call doesn't match the handlingHost
|
||||
if (optionalRecipient != null && !optionalRecipient.getEntityName().equals(optionalTarget))
|
||||
return 0;
|
||||
List<Value> args = runtimeArgs;
|
||||
if (!this.parametrizedArgs.isEmpty())
|
||||
{
|
||||
args = new ArrayList<>(runtimeArgs);
|
||||
args.addAll(this.parametrizedArgs);
|
||||
}
|
||||
return CarpetServer.scriptServer.runForPlayer(recipient, host, function, args);
|
||||
return CarpetServer.scriptServer.signal(sender, optionalRecipient, host, function, args, false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return function.getString()+((host==null)?"":"(from "+host+")");
|
||||
return function.getString()+((host==null)?"":"(from "+host+(optionalTarget == null?"":"/"+optionalTarget)+")");
|
||||
}
|
||||
public static class Signature
|
||||
{
|
||||
String function;
|
||||
String host;
|
||||
String target;
|
||||
public Signature(String fun, String h, String t)
|
||||
{
|
||||
function = fun;
|
||||
host = h;
|
||||
target = t;
|
||||
}
|
||||
}
|
||||
public static Signature fromString(String str)
|
||||
{
|
||||
Pattern find = Pattern.compile("(\\w+)(?:\\(from (\\w+)(?:/(\\w+))?\\))?");
|
||||
Matcher matcher = find.matcher(str);
|
||||
if(matcher.matches())
|
||||
{
|
||||
return new Signature(matcher.group(1), matcher.group(2), matcher.group(3));
|
||||
}
|
||||
return new Signature(str, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +156,8 @@ public class CarpetEventServer
|
||||
|
||||
public ScheduledCall(CarpetContext context, FunctionValue function, List<Value> args, long dueTime)
|
||||
{
|
||||
super(context.host.getName(), function, args);
|
||||
// ignoring target as we will be always calling self
|
||||
super(context.host.getName(), null, function, args);
|
||||
this.ctx = context;
|
||||
this.dueTime = dueTime;
|
||||
}
|
||||
@@ -139,7 +167,7 @@ public class CarpetEventServer
|
||||
*/
|
||||
public void execute()
|
||||
{
|
||||
CarpetServer.scriptServer.runas(ctx.origin, ctx.s, host, function, parametrizedArgs);
|
||||
CarpetServer.scriptServer.runScheduledCall(ctx.origin, ctx.s, host, (CarpetScriptHost) ctx.host, function, parametrizedArgs);
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +201,7 @@ public class CarpetEventServer
|
||||
}
|
||||
}
|
||||
|
||||
public int callCustom(ServerPlayerEntity receipient, List<Value> callArg)
|
||||
public int signal(ServerCommandSource sender, ServerPlayerEntity optinoalReceipient, List<Value> callArg)
|
||||
{
|
||||
if (callList.isEmpty()) return 0;
|
||||
//List<Callback> fails = new ArrayList<>();
|
||||
@@ -181,15 +209,13 @@ public class CarpetEventServer
|
||||
int successes = 0;
|
||||
for (Callback call: callList)
|
||||
{
|
||||
Boolean result = call.targetPlayer(receipient, callArg);
|
||||
//if (result == Boolean.FALSE) fails.add(call);
|
||||
if (result == Boolean.TRUE) successes++;
|
||||
successes += Math.max(0, call.signal(sender, optinoalReceipient, callArg));
|
||||
}
|
||||
//for (Callback call : fails) callList.remove(call);
|
||||
return successes;
|
||||
}
|
||||
|
||||
public boolean addEventCall(ServerCommandSource source, String hostName, String funName, Function<ScriptHost, Boolean> verifier)
|
||||
public boolean addFromExternal(ServerCommandSource source, String hostName, String funName, Consumer<ScriptHost> hostOnEventHandler)
|
||||
{
|
||||
ScriptHost host = CarpetServer.scriptServer.getHostByName(hostName);
|
||||
if (host == null)
|
||||
@@ -198,11 +224,7 @@ public class CarpetEventServer
|
||||
Messenger.m(source, "r Unknown app "+hostName);
|
||||
return false;
|
||||
}
|
||||
if (!verifier.apply(host))
|
||||
{
|
||||
Messenger.m(source, "r Global event can only be added to apps with global scope");
|
||||
return false;
|
||||
}
|
||||
hostOnEventHandler.accept(host);
|
||||
FunctionValue udf = host.getFunction(funName);
|
||||
if (udf == null || udf.getArguments().size() != reqArgs)
|
||||
{
|
||||
@@ -210,11 +232,24 @@ public class CarpetEventServer
|
||||
Messenger.m(source, "r Callback doesn't expect required number of arguments: "+reqArgs);
|
||||
return false;
|
||||
}
|
||||
String target = null;
|
||||
if (host.isPerUser())
|
||||
{
|
||||
try
|
||||
{
|
||||
target = source.getPlayer().getEntityName();
|
||||
}
|
||||
catch (CommandSyntaxException e)
|
||||
{
|
||||
Messenger.m(source, "r Cannot add event to a player scoped app from a command without a player context");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//all clear
|
||||
//remove duplicates
|
||||
|
||||
removeEventCall(hostName, udf.getString());
|
||||
callList.add(new Callback(hostName, udf, null));
|
||||
removeEventCall(hostName, target, udf.getString());
|
||||
callList.add(new Callback(hostName, target, udf, null));
|
||||
return true;
|
||||
}
|
||||
public boolean addEventCallInternal(ScriptHost host, FunctionValue function, List<Value> args)
|
||||
@@ -225,20 +260,39 @@ public class CarpetEventServer
|
||||
}
|
||||
//all clear
|
||||
//remove duplicates
|
||||
removeEventCall(host.getName(), function.getString());
|
||||
callList.add(new Callback(host.getName(), function, args));
|
||||
removeEventCall(host.getName(), host.user, function.getString());
|
||||
callList.add(new Callback(host.getName(), host.user, function, args));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void removeEventCall(String hostName, String funName)
|
||||
public void removeEventCall(String hostName, String target, String funName)
|
||||
{
|
||||
callList.removeIf((c)-> c.function.getString().equals(funName) && ( hostName == c.host || (c.host != null && c.host.equalsIgnoreCase(hostName) )) );
|
||||
callList.removeIf((c)-> c.function.getString().equals(funName)
|
||||
&& (Objects.equals(c.host, hostName))
|
||||
&& (Objects.equals(c.optionalTarget, target))
|
||||
);
|
||||
}
|
||||
|
||||
public void removeAllCalls(CarpetScriptHost host)
|
||||
{
|
||||
callList.removeIf((c)-> c.host != null && c.host.equals(host.getName()));
|
||||
callList.removeIf((c)-> (Objects.equals(c.host, host.getName()))
|
||||
&& (Objects.equals(c.optionalTarget, host.user)));
|
||||
}
|
||||
|
||||
public void createChildEvents(CarpetScriptHost host)
|
||||
{
|
||||
List<Callback> copyCalls = new ArrayList<>();
|
||||
callList.forEach((c)->
|
||||
{
|
||||
if ((Objects.equals(c.host, host.getName()))
|
||||
&& c.optionalTarget == null)
|
||||
{
|
||||
copyCalls.add(new Callback(c.host, host.user, c.function, c.parametrizedArgs));
|
||||
}
|
||||
});
|
||||
callList.addAll(copyCalls);
|
||||
}
|
||||
|
||||
public void clearEverything()
|
||||
{
|
||||
callList.clear();
|
||||
@@ -801,6 +855,12 @@ public class CarpetEventServer
|
||||
host.getScriptServer().events.customEvents.values().forEach((e) -> e.handler.removeAllCalls(host));
|
||||
}
|
||||
|
||||
public static void transferAllHostEventsToChild(CarpetScriptHost host)
|
||||
{
|
||||
byName.values().forEach((e) -> e.handler.createChildEvents(host));
|
||||
host.getScriptServer().events.customEvents.values().forEach((e) -> e.handler.createChildEvents(host));
|
||||
}
|
||||
|
||||
public static void clearAllBuiltinEvents()
|
||||
{
|
||||
byName.values().forEach(e -> e.handler.clearEverything());
|
||||
@@ -888,7 +948,7 @@ public class CarpetEventServer
|
||||
{
|
||||
return false;
|
||||
}
|
||||
boolean added = ev.handler.addEventCall(source, host, funName, h -> canAddEvent(ev, h));
|
||||
boolean added = ev.handler.addFromExternal(source, host, funName, h -> onEventAddedToHost(ev, h));
|
||||
if (added) Messenger.m(source, "gi Added " + funName + " to " + event);
|
||||
return added;
|
||||
}
|
||||
@@ -897,8 +957,7 @@ public class CarpetEventServer
|
||||
{
|
||||
// this is globals only
|
||||
Event ev = Event.byName.get(event);
|
||||
if (!canAddEvent(ev, host))
|
||||
throw new InternalExpressionException("Global event "+event+" can only be added to apps with global scope");
|
||||
onEventAddedToHost(ev, host);
|
||||
boolean success = ev.handler.addEventCallInternal(host, function, args==null?NOARGS:args);
|
||||
if (!success) throw new InternalExpressionException("Global event "+event+" requires "+ev.handler.reqArgs+", not "+(function.getNumParams()-((args==null)?0:args.size())));
|
||||
}
|
||||
@@ -906,22 +965,21 @@ public class CarpetEventServer
|
||||
public boolean handleCustomEvent(String event, CarpetScriptHost host, FunctionValue function, List<Value> args)
|
||||
{
|
||||
Event ev = Event.getOrCreateCustom(event, host.getScriptServer());
|
||||
if (!canAddEvent(ev, host))
|
||||
throw new InternalExpressionException("Global built-in event "+event+" can only be handled in apps with global scope");
|
||||
onEventAddedToHost(ev, host);
|
||||
return ev.handler.addEventCallInternal(host, function, args==null?NOARGS:args);
|
||||
}
|
||||
|
||||
public int signalEvent(String event, CarpetScriptHost host, ServerPlayerEntity player, List<Value> callArgs)
|
||||
public int signalEvent(String event, CarpetContext cc, ServerPlayerEntity optionalTarget, List<Value> callArgs)
|
||||
{
|
||||
Event ev = Event.getEvent(event, host.getScriptServer());
|
||||
Event ev = Event.getEvent(event, ((CarpetScriptHost)cc.host).getScriptServer());
|
||||
if (ev == null) return -1;
|
||||
return ev.handler.callCustom(player, callArgs);
|
||||
return ev.handler.signal(cc.s, optionalTarget, callArgs);
|
||||
}
|
||||
|
||||
private boolean canAddEvent(Event event, ScriptHost host)
|
||||
private void onEventAddedToHost(Event event, ScriptHost host)
|
||||
{
|
||||
if (event.deprecated()) host.issueDeprecation(event.name+" event");
|
||||
return !(event.globalOnly && (host.perUser || host.parent != null));
|
||||
//return !(event.globalOnly && (host.perUser || host.parent != null));
|
||||
}
|
||||
|
||||
public boolean removeEventFromCommand(ServerCommandSource source, String event, String funName)
|
||||
@@ -932,8 +990,8 @@ public class CarpetEventServer
|
||||
Messenger.m(source, "r Unknown event: " + event);
|
||||
return false;
|
||||
}
|
||||
Pair<String,String> call = decodeCallback(funName);
|
||||
ev.handler.removeEventCall(call.getLeft(), call.getRight());
|
||||
Callback.Signature call = Callback.fromString(funName);
|
||||
ev.handler.removeEventCall(call.host, call.target, call.function);
|
||||
// could verified if actually removed
|
||||
Messenger.m(source, "gi Removed event: " + funName + " from "+event);
|
||||
return true;
|
||||
@@ -949,13 +1007,15 @@ public class CarpetEventServer
|
||||
public void removeBuiltInEvent(String event, CarpetScriptHost host, String funName)
|
||||
{
|
||||
Event ev = Event.getEvent(event, host.getScriptServer());
|
||||
if (ev != null) ev.handler.removeEventCall(host.getName(), funName);
|
||||
if (ev != null) ev.handler.removeEventCall(host.getName(), host.user, funName);
|
||||
}
|
||||
|
||||
public void removeAllHostEvents(CarpetScriptHost host)
|
||||
{
|
||||
// remove event handlers
|
||||
Event.removeAllHostEvents(host);
|
||||
if (host.isPerUser())
|
||||
for (ScriptHost child: host.userHosts.values()) Event.removeAllHostEvents((CarpetScriptHost) child);
|
||||
// remove scheduled calls
|
||||
scheduledCalls.removeIf(sc -> sc.host != null && sc.host.equals(host.getName()));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package carpet.script;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.script.api.Auxiliary;
|
||||
import carpet.script.argument.FunctionArgument;
|
||||
import carpet.script.bundled.Module;
|
||||
@@ -15,7 +16,6 @@ import carpet.script.value.MapValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.script.value.Value;
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.utils.Messenger;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
@@ -117,7 +117,7 @@ public class CarpetScriptHost extends ScriptHost
|
||||
|
||||
private static int execute(CommandContext<ServerCommandSource> ctx, String hostName, FunctionArgument<Value> funcSpec, List<String> paramNames) throws CommandSyntaxException
|
||||
{
|
||||
CarpetScriptHost cHost = CarpetServer.scriptServer.modules.get(hostName).retrieveForExecution(ctx.getSource());
|
||||
CarpetScriptHost cHost = CarpetServer.scriptServer.modules.get(hostName).retrieveOwnForExecution(ctx.getSource());
|
||||
List<String> argNames = funcSpec.function.getArguments();
|
||||
if ((argNames.size()-funcSpec.args.size()) != paramNames.size())
|
||||
throw new SimpleCommandExceptionType(new LiteralText("Target function "+funcSpec.function.getPrettyString()+" as wrong number of arguments, required "+paramNames.size()+", found "+argNames.size()+" with "+funcSpec.args.size()+" provided")).create();
|
||||
@@ -177,6 +177,14 @@ public class CarpetScriptHost extends ScriptHost
|
||||
return new CarpetScriptHost(scriptServer, main, false, this, appConfig, appArgTypes, commandValidator, isRuleApp);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void transferToChild(ScriptHost host)
|
||||
{
|
||||
super.transferToChild(host);
|
||||
// transfer Events
|
||||
CarpetEventServer.Event.transferAllHostEventsToChild((CarpetScriptHost) host);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addUserDefinedFunction(Context ctx, Module module, String funName, FunctionValue function)
|
||||
{
|
||||
@@ -319,38 +327,58 @@ public class CarpetScriptHost extends ScriptHost
|
||||
}
|
||||
}
|
||||
|
||||
public CarpetScriptHost retrieveForExecution(ServerCommandSource source)
|
||||
public List<CarpetScriptHost> retrieveForExecution(ServerCommandSource source, String optionalTarget)
|
||||
{
|
||||
CarpetScriptHost host = this;
|
||||
List<CarpetScriptHost> targets = new ArrayList<>();
|
||||
if (perUser)
|
||||
{
|
||||
try
|
||||
if (optionalTarget == null)
|
||||
{
|
||||
ServerPlayerEntity player = source.getPlayer();
|
||||
host = (CarpetScriptHost) retrieveForExecution(player.getName().getString());
|
||||
for (ServerPlayerEntity player : source.getMinecraftServer().getPlayerManager().getPlayerList())
|
||||
{
|
||||
CarpetScriptHost host = (CarpetScriptHost) retrieveForExecution(player.getEntityName());
|
||||
targets.add(host);
|
||||
if (host.errorSnooper == null) host.setChatErrorSnooper(player.getCommandSource());
|
||||
}
|
||||
}
|
||||
catch (CommandSyntaxException e)
|
||||
else
|
||||
{
|
||||
host = (CarpetScriptHost) retrieveForExecution((String) null);
|
||||
ServerPlayerEntity player = source.getMinecraftServer().getPlayerManager().getPlayer(optionalTarget);
|
||||
if (player != null)
|
||||
{
|
||||
CarpetScriptHost host = (CarpetScriptHost) retrieveForExecution(player.getEntityName());
|
||||
targets.add(host);
|
||||
if (host.errorSnooper == null) host.setChatErrorSnooper(player.getCommandSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (host.errorSnooper == null) host.setChatErrorSnooper(source);
|
||||
return host;
|
||||
else
|
||||
{
|
||||
targets.add(this);
|
||||
if (this.errorSnooper == null) this.setChatErrorSnooper(source);
|
||||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
public CarpetScriptHost retrieveForExecution(ServerPlayerEntity target)
|
||||
public CarpetScriptHost retrieveOwnForExecution(ServerCommandSource source) throws CommandSyntaxException
|
||||
{
|
||||
// allowing only run
|
||||
if (perUser == (target == null)) return null;
|
||||
|
||||
if (!perUser)
|
||||
{
|
||||
if (errorSnooper == null) setChatErrorSnooper(this.scriptServer.server.getCommandSource());
|
||||
if (errorSnooper == null) setChatErrorSnooper(source);
|
||||
return this;
|
||||
}
|
||||
// user based
|
||||
CarpetScriptHost userHost = (CarpetScriptHost)retrieveForExecution(target.getName().getString());
|
||||
if (userHost.errorSnooper == null) userHost.setChatErrorSnooper(target.getCommandSource());
|
||||
ServerPlayerEntity player;
|
||||
try
|
||||
{
|
||||
player = source.getPlayer();
|
||||
}
|
||||
catch (CommandSyntaxException ignored)
|
||||
{
|
||||
throw new SimpleCommandExceptionType(new LiteralText("Cannot run player based apps without the player context")).create();
|
||||
}
|
||||
CarpetScriptHost userHost = (CarpetScriptHost)retrieveForExecution(player.getEntityName());
|
||||
if (userHost.errorSnooper == null) userHost.setChatErrorSnooper(source);
|
||||
return userHost;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package carpet.script;
|
||||
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.script.argument.FunctionArgument;
|
||||
import carpet.script.bundled.BundledModule;
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.CarpetServer;
|
||||
import carpet.script.bundled.FileModule;
|
||||
import carpet.script.bundled.Module;
|
||||
@@ -296,6 +296,11 @@ public class CarpetScriptServer
|
||||
Messenger.m(source, "r Failed to build command system for "+name+" thus failed to load the app");
|
||||
return false;
|
||||
}
|
||||
if (newHost.isPerUser())
|
||||
{
|
||||
// that will provide player hosts right at the startup
|
||||
newHost.retrieveForExecution(source, null);
|
||||
}
|
||||
long end = System.nanoTime();
|
||||
CarpetSettings.LOG.info("App "+name+" loaded in "+(end-start)/1000000+" ms");
|
||||
return true;
|
||||
@@ -325,8 +330,8 @@ public class CarpetScriptServer
|
||||
requires((player) -> modules.containsKey(hostName) && useValidator.apply(player)).
|
||||
executes( (c) ->
|
||||
{
|
||||
Value response = modules.get(hostName).retrieveForExecution(c.getSource()).
|
||||
handleCommandLegacy(c.getSource(),"__command", null, "");
|
||||
CarpetScriptHost targetHost = modules.get(hostName).retrieveOwnForExecution(c.getSource());
|
||||
Value response = targetHost.handleCommandLegacy(c.getSource(),"__command", null, "");
|
||||
if (!response.isNull()) Messenger.m(c.getSource(), "gi "+response.getString());
|
||||
return (int)response.readInteger();
|
||||
});
|
||||
@@ -355,15 +360,15 @@ public class CarpetScriptServer
|
||||
then(literal(function).
|
||||
requires((player) -> modules.containsKey(hostName) && modules.get(hostName).getFunction(function) != null).
|
||||
executes((c) -> {
|
||||
Value response = modules.get(hostName).retrieveForExecution(c.getSource()).
|
||||
handleCommandLegacy(c.getSource(), function, null, "");
|
||||
CarpetScriptHost targetHost = modules.get(hostName).retrieveOwnForExecution(c.getSource());
|
||||
Value response = targetHost.handleCommandLegacy(c.getSource(),function, null, "");
|
||||
if (!response.isNull()) Messenger.m(c.getSource(), "gi " + response.getString());
|
||||
return (int) response.readInteger();
|
||||
}).
|
||||
then(argument("args...", StringArgumentType.greedyString()).
|
||||
executes( (c) -> {
|
||||
Value response = modules.get(hostName).retrieveForExecution(c.getSource()).
|
||||
handleCommandLegacy(c.getSource(), function,null, StringArgumentType.getString(c, "args..."));
|
||||
CarpetScriptHost targetHost = modules.get(hostName).retrieveOwnForExecution(c.getSource());
|
||||
Value response = targetHost.handleCommandLegacy(c.getSource(),function, null, StringArgumentType.getString(c, "args..."));
|
||||
if (!response.isNull()) Messenger.m(c.getSource(), "gi "+response.getString());
|
||||
return (int)response.readInteger();
|
||||
})));
|
||||
@@ -394,54 +399,84 @@ public class CarpetScriptServer
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean runas(ServerCommandSource source, String hostname, FunctionValue udf, List<Value> argv)
|
||||
{
|
||||
return runas(BlockPos.ORIGIN, source, hostname, udf, argv);
|
||||
}
|
||||
|
||||
public boolean runas(BlockPos origin, ServerCommandSource source, String hostname, FunctionValue udf, List<Value> argv)
|
||||
public boolean runEventCall(ServerCommandSource sender, String hostname, String optionalTarget, FunctionValue udf, List<Value> argv)
|
||||
{
|
||||
CarpetScriptHost host = globalHost;
|
||||
try
|
||||
if (hostname != null)
|
||||
host = modules.get(hostname);
|
||||
if (host == null) return false;
|
||||
// dummy call for player apps that reside on the global copy - do not run them, but report as successes.
|
||||
if (host.isPerUser() && optionalTarget==null) return true;
|
||||
ServerPlayerEntity target = null;
|
||||
if (optionalTarget != null)
|
||||
{
|
||||
if (hostname != null)
|
||||
host = modules.get(hostname).retrieveForExecution(source);
|
||||
host.callUDF(origin, source, udf, argv);
|
||||
target = sender.getMinecraftServer().getPlayerManager().getPlayer(optionalTarget);
|
||||
if (target == null) return false;
|
||||
}
|
||||
catch (NullPointerException | InvalidCallbackException npe)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
int successes = signal(sender, target, hostname, udf, argv, true );
|
||||
return successes >= 0;
|
||||
}
|
||||
|
||||
public Boolean runForPlayer(ServerPlayerEntity recipient, String hostname, FunctionValue udf, List<Value> argv)
|
||||
public void runScheduledCall(BlockPos origin, ServerCommandSource source, String hostname, CarpetScriptHost host, FunctionValue udf, List<Value> argv)
|
||||
{
|
||||
if (hostname != null && !modules.containsKey(hostname)) // well - scheduled call app got unloaded
|
||||
return;
|
||||
try
|
||||
{
|
||||
host.callUDF(origin, source, udf, argv);
|
||||
}
|
||||
catch (NullPointerException | InvalidCallbackException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns number of successful calls in the host or -1 if failed exceptionally
|
||||
* @param sender
|
||||
* @param optionalRecipient
|
||||
* @param hostname
|
||||
* @param udf
|
||||
* @param argv
|
||||
* @param reportFails - returns -1 when any call failed
|
||||
* @return
|
||||
*/
|
||||
public int signal(ServerCommandSource sender, ServerPlayerEntity optionalRecipient, String hostname, FunctionValue udf, List<Value> argv, boolean reportFails)
|
||||
{
|
||||
CarpetScriptHost host;
|
||||
ServerCommandSource source;
|
||||
|
||||
if (hostname == null)
|
||||
{
|
||||
if (recipient != null) return null;
|
||||
host = globalHost;
|
||||
source = server.getCommandSource();
|
||||
if (optionalRecipient != null) return 0;
|
||||
try
|
||||
{
|
||||
globalHost.callUDF(BlockPos.ORIGIN, sender, udf, argv);
|
||||
}
|
||||
catch (NullPointerException | InvalidCallbackException npe)
|
||||
{
|
||||
return reportFails?-1:0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
String hostRecipient = optionalRecipient == null?null:optionalRecipient.getEntityName();
|
||||
ServerCommandSource source = (optionalRecipient == null)? sender : optionalRecipient.getCommandSource().withLevel(CarpetSettings.runPermissionLevel);
|
||||
int successes = 0;
|
||||
for (CarpetScriptHost host : modules.get(hostname).retrieveForExecution(sender, hostRecipient))
|
||||
{
|
||||
host = modules.get(hostname).retrieveForExecution(recipient);
|
||||
if (host == null) // not applicable
|
||||
return null;
|
||||
source = (recipient == null)? server.getCommandSource() : recipient.getCommandSource();
|
||||
// getPlayer will always return nonnull cause retrieve for execution only returns hosts for existing players.
|
||||
ServerCommandSource executingSource = host.perUser
|
||||
? source.getMinecraftServer().getPlayerManager().getPlayer(host.user).getCommandSource()
|
||||
: source.getMinecraftServer().getCommandSource();
|
||||
try
|
||||
{
|
||||
host.callUDF(BlockPos.ORIGIN, source.withLevel(CarpetSettings.runPermissionLevel), udf, argv);
|
||||
}
|
||||
catch (NullPointerException | InvalidCallbackException npe)
|
||||
{
|
||||
if (reportFails) return -1;
|
||||
continue;
|
||||
}
|
||||
successes ++;
|
||||
}
|
||||
try
|
||||
{
|
||||
host.callUDF(BlockPos.ORIGIN, source.withLevel(CarpetSettings.runPermissionLevel), udf, argv);
|
||||
}
|
||||
catch (NullPointerException | InvalidCallbackException npe)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return successes;
|
||||
}
|
||||
|
||||
public void tick()
|
||||
@@ -461,6 +496,23 @@ public class CarpetScriptServer
|
||||
}
|
||||
}
|
||||
|
||||
public void onPlayerJoin(ServerPlayerEntity player)
|
||||
{
|
||||
modules.values().forEach(h ->
|
||||
{
|
||||
if (h.isPerUser())
|
||||
{
|
||||
try
|
||||
{
|
||||
h.retrieveOwnForExecution(player.getCommandSource());
|
||||
}
|
||||
catch (CommandSyntaxException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static class TransferData
|
||||
{
|
||||
boolean perUser;
|
||||
|
||||
@@ -9,6 +9,7 @@ import carpet.script.value.StringValue;
|
||||
import carpet.script.value.Value;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -19,7 +20,7 @@ import java.util.Map;
|
||||
|
||||
public class EntityEventsGroup
|
||||
{
|
||||
private final Map<Event, Map<String, CarpetEventServer.Callback>> actions;
|
||||
private final Map<Event, Map<Pair<String,String>, CarpetEventServer.Callback>> actions;
|
||||
private final Entity entity;
|
||||
public EntityEventsGroup(Entity e)
|
||||
{
|
||||
@@ -30,37 +31,47 @@ public class EntityEventsGroup
|
||||
public void onEvent(Event type, Object... args)
|
||||
{
|
||||
if (actions.isEmpty()) return; // most of the cases, trying to be nice
|
||||
Map<String, CarpetEventServer.Callback> actionSet = actions.get(type);
|
||||
Map<Pair<String,String>, CarpetEventServer.Callback> actionSet = actions.get(type);
|
||||
if (actionSet == null) return;
|
||||
|
||||
|
||||
for (Iterator<Map.Entry<String, CarpetEventServer.Callback>> iterator = actionSet.entrySet().iterator(); iterator.hasNext(); )
|
||||
for (Iterator<Map.Entry<Pair<String,String>, CarpetEventServer.Callback>> iterator = actionSet.entrySet().iterator(); iterator.hasNext(); )
|
||||
{
|
||||
Map.Entry<String, CarpetEventServer.Callback> action = iterator.next();
|
||||
ScriptHost host = CarpetServer.scriptServer.getHostByName(action.getKey());
|
||||
Map.Entry<Pair<String,String>, CarpetEventServer.Callback> action = iterator.next();
|
||||
Pair<String,String> key = action.getKey();
|
||||
ScriptHost host = CarpetServer.scriptServer.getHostByName(key.getLeft());
|
||||
if (host == null)
|
||||
{
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
if (key.getRight() != null)
|
||||
{
|
||||
if (entity.getServer().getPlayerManager().getPlayer(key.getRight())==null)
|
||||
{
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!type.call(action.getValue(), entity, args))
|
||||
iterator.remove();
|
||||
}
|
||||
if (actionSet.isEmpty()) actions.remove(type);
|
||||
}
|
||||
|
||||
public void addEvent(Event type, String hostName, FunctionValue fun, List<Value> extraargs)
|
||||
public void addEvent(Event type, ScriptHost host, FunctionValue fun, List<Value> extraargs)
|
||||
{
|
||||
Pair<String,String> key = Pair.of(host.getName(), host.user);
|
||||
if (fun != null)
|
||||
{
|
||||
CarpetEventServer.Callback call = type.create(hostName, fun, extraargs);
|
||||
CarpetEventServer.Callback call = type.create(key, fun, extraargs);
|
||||
if (call == null)
|
||||
throw new InternalExpressionException("wrong number of arguments for callback, required "+type.argcount);
|
||||
actions.computeIfAbsent(type, k -> new HashMap<>()).put(hostName, call);
|
||||
actions.computeIfAbsent(type, k -> new HashMap<>()).put(key, call);
|
||||
}
|
||||
else
|
||||
{
|
||||
actions.computeIfAbsent(type, k -> new HashMap<>()).remove(hostName);
|
||||
actions.computeIfAbsent(type, k -> new HashMap<>()).remove(key);
|
||||
if (actions.get(type).isEmpty())
|
||||
actions.remove(type);
|
||||
}
|
||||
@@ -107,13 +118,13 @@ public class EntityEventsGroup
|
||||
argcount = args+1; // entity is not extra
|
||||
byName.put(identifier, this);
|
||||
}
|
||||
public CarpetEventServer.Callback create(String hostName, FunctionValue function, List<Value> extraArgs)
|
||||
public CarpetEventServer.Callback create(Pair<String,String> key, FunctionValue function, List<Value> extraArgs)
|
||||
{
|
||||
if ((function.getArguments().size()-(extraArgs == null ? 0 : extraArgs.size())) != argcount)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new CarpetEventServer.Callback(hostName, function, extraArgs);
|
||||
return new CarpetEventServer.Callback(key.getLeft(), key.getRight(), function, extraArgs);
|
||||
}
|
||||
public boolean call(CarpetEventServer.Callback tickCall, Entity entity, Object ... args)
|
||||
{
|
||||
|
||||
@@ -318,15 +318,21 @@ public abstract class ScriptHost
|
||||
ScriptHost oldUserHost = userHosts.get(user);
|
||||
if (oldUserHost != null) return oldUserHost;
|
||||
ScriptHost userHost = this.duplicate();
|
||||
userHost.modules.putAll(this.modules);
|
||||
this.moduleData.forEach((key, value) -> userHost.moduleData.put(key, new ModuleData(key, value)));
|
||||
// fixing imports
|
||||
userHost.moduleData.forEach((module, data) -> data.setImportsBasedOn(userHost, this.moduleData.get(data.parent)));
|
||||
userHost.user = user;
|
||||
this.transferToChild(userHost);
|
||||
userHosts.put(user, userHost);
|
||||
return userHost;
|
||||
}
|
||||
|
||||
protected void transferToChild(ScriptHost host)
|
||||
{
|
||||
// adding imports
|
||||
host.modules.putAll(this.modules);
|
||||
this.moduleData.forEach((key, value) -> host.moduleData.put(key, new ModuleData(key, value)));
|
||||
// fixing imports
|
||||
host.moduleData.forEach((module, data) -> data.setImportsBasedOn(host, this.moduleData.get(data.parent)));
|
||||
}
|
||||
|
||||
public void handleExpressionException(String msg, ExpressionException exc)
|
||||
{
|
||||
System.out.println(msg+": "+exc);
|
||||
|
||||
@@ -961,6 +961,7 @@ public class Auxiliary {
|
||||
{
|
||||
if (lv.size() == 0)
|
||||
throw new InternalExpressionException("'signal' requires at least one argument");
|
||||
CarpetContext cc = (CarpetContext)c;
|
||||
CarpetScriptServer server = ((CarpetScriptHost)c.host).getScriptServer();
|
||||
String eventName = lv.get(0).evalValue(c).getString();
|
||||
// no such event yet
|
||||
@@ -975,10 +976,10 @@ public class Auxiliary {
|
||||
args = FunctionValue.resolveArgs(lv.subList(2, lv.size()), c, t);
|
||||
}
|
||||
}
|
||||
int counts = ((CarpetScriptHost)c.host).getScriptServer().events.signalEvent(eventName, (CarpetScriptHost) c.host, player, args);
|
||||
int counts = ((CarpetScriptHost)c.host).getScriptServer().events.signalEvent(eventName, cc, player, args);
|
||||
if (counts < 0) return LazyValue.NULL;
|
||||
Value ret = new NumericValue(counts);
|
||||
return (cc, tt) -> ret;
|
||||
return (c_, t_) -> ret;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@ import carpet.script.value.StringValue;
|
||||
import carpet.script.value.FormattedTextValue;
|
||||
import carpet.script.value.Value;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.boss.BossBar;
|
||||
import net.minecraft.entity.boss.BossBarManager;
|
||||
import net.minecraft.entity.boss.CommandBossBar;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.scoreboard.Scoreboard;
|
||||
import net.minecraft.scoreboard.ServerScoreboard;
|
||||
@@ -20,9 +23,12 @@ import net.minecraft.scoreboard.ScoreboardObjective;
|
||||
import net.minecraft.scoreboard.ScoreboardPlayerScore;
|
||||
import net.minecraft.scoreboard.Team;
|
||||
import net.minecraft.scoreboard.AbstractTeam;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.InvalidIdentifierException;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -396,6 +402,131 @@ public class Scoreboards {
|
||||
}
|
||||
return LazyValue.TRUE;
|
||||
});
|
||||
|
||||
expression.addLazyFunction("bossbar", -1, (c, t, lv) ->
|
||||
{
|
||||
BossBarManager bossBarManager = ((CarpetContext)c).s.getMinecraftServer().getBossBarManager();
|
||||
if(lv.size() > 3) throw new InternalExpressionException("'bossbar' accepts max three arguments");
|
||||
|
||||
if(lv.size() == 0) {
|
||||
Value ret = ListValue.wrap(bossBarManager.getAll().stream().map(CommandBossBar::getId).map(Identifier::toString).map(StringValue::of).collect(Collectors.toList()));
|
||||
return (_c, _t) -> ret;
|
||||
}
|
||||
|
||||
String id = lv.get(0).evalValue(c).getString();
|
||||
Identifier identifier;
|
||||
try {
|
||||
identifier = new Identifier(id);
|
||||
} catch (InvalidIdentifierException invalidIdentifierException) {
|
||||
return LazyValue.NULL;
|
||||
}
|
||||
|
||||
if(lv.size() == 1) {
|
||||
if(bossBarManager.get(identifier) != null) return LazyValue.FALSE;
|
||||
Value ret = StringValue.of(bossBarManager.add(identifier,new LiteralText(id)).getId().toString());
|
||||
return (_c, _t) -> ret;
|
||||
}
|
||||
|
||||
String property = lv.get(1).evalValue(c).getString();
|
||||
|
||||
CommandBossBar bossBar = bossBarManager.get(identifier);
|
||||
if(bossBar == null) return LazyValue.NULL;
|
||||
|
||||
Value propertyValue = (lv.size() == 3)?lv.get(2).evalValue(c):null;
|
||||
|
||||
switch (property) {
|
||||
case "color":
|
||||
if(propertyValue == null) {
|
||||
BossBar.Color color = (bossBar).getColor();
|
||||
if(color == null) return LazyValue.NULL;
|
||||
return (_c, _t) -> StringValue.of(color.getName());
|
||||
}
|
||||
|
||||
BossBar.Color color = BossBar.Color.byName(propertyValue.getString());
|
||||
if(color == null) return LazyValue.NULL;
|
||||
bossBar.setColor(BossBar.Color.byName(propertyValue.getString()));
|
||||
return LazyValue.TRUE;
|
||||
case "max":
|
||||
if(propertyValue == null) return (_c, _t) -> NumericValue.of(bossBar.getMaxValue());
|
||||
|
||||
if(!(propertyValue instanceof NumericValue)) throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property);
|
||||
bossBar.setMaxValue(((NumericValue) propertyValue).getInt());
|
||||
return LazyValue.TRUE;
|
||||
case "name":
|
||||
if(propertyValue == null) return (_c, _t) -> new FormattedTextValue(bossBar.getName());
|
||||
|
||||
if(propertyValue instanceof FormattedTextValue) {
|
||||
bossBar.setName(((FormattedTextValue) propertyValue).getText());
|
||||
} else {
|
||||
bossBar.setName(new LiteralText(propertyValue.getString()));
|
||||
}
|
||||
return LazyValue.TRUE;
|
||||
case "add_player":
|
||||
if(propertyValue == null) throw new InternalExpressionException("Bossbar property " + property + " can't be queried, add a third parameter");
|
||||
|
||||
if(propertyValue instanceof ListValue) {
|
||||
((ListValue) propertyValue).getItems().forEach((v)->{
|
||||
ServerPlayerEntity player = EntityValue.getPlayerByValue(((CarpetContext)c).s.getMinecraftServer(),propertyValue);
|
||||
if(player != null) bossBar.addPlayer(player);
|
||||
});
|
||||
return LazyValue.TRUE;
|
||||
}
|
||||
|
||||
ServerPlayerEntity player = EntityValue.getPlayerByValue(((CarpetContext) c).s.getMinecraftServer(), propertyValue);
|
||||
if(player != null) {
|
||||
bossBar.addPlayer(player);
|
||||
return LazyValue.TRUE;
|
||||
}
|
||||
return LazyValue.FALSE;
|
||||
case "players":
|
||||
if(propertyValue == null) {
|
||||
return (_c, _t) -> ListValue.wrap(bossBar.getPlayers().stream().map(EntityValue::new).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
if(propertyValue instanceof ListValue) {
|
||||
bossBar.clearPlayers();
|
||||
((ListValue) propertyValue).getItems().forEach((v) -> {
|
||||
ServerPlayerEntity p = EntityValue.getPlayerByValue(((CarpetContext) c).s.getMinecraftServer(), v);
|
||||
if (p != null) bossBar.addPlayer(p);
|
||||
});
|
||||
return LazyValue.TRUE;
|
||||
}
|
||||
|
||||
|
||||
ServerPlayerEntity p = EntityValue.getPlayerByValue(((CarpetContext) c).s.getMinecraftServer(), propertyValue);
|
||||
bossBar.clearPlayers();
|
||||
if (p != null) {
|
||||
bossBar.addPlayer(p);
|
||||
return LazyValue.TRUE;
|
||||
}
|
||||
return LazyValue.FALSE;
|
||||
case "style":
|
||||
if(propertyValue == null) {
|
||||
return (_c, _t) -> StringValue.of(bossBar.getOverlay().getName());
|
||||
}
|
||||
|
||||
BossBar.Style style = BossBar.Style.byName(propertyValue.getString());
|
||||
if(style == null) throw new InternalExpressionException("'" + propertyValue.getString() + "' is not a valid value for property " + property);
|
||||
bossBar.setOverlay(style);
|
||||
return LazyValue.TRUE;
|
||||
case "value":
|
||||
if(propertyValue == null) return (_c, _t) -> NumericValue.of(bossBar.getValue());
|
||||
|
||||
if(!(propertyValue instanceof NumericValue)) throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property);
|
||||
bossBar.setValue(((NumericValue) propertyValue).getInt());
|
||||
return LazyValue.TRUE;
|
||||
case "visible":
|
||||
if(propertyValue == null) return (_c, _t) -> new NumericValue(bossBar.isVisible());
|
||||
|
||||
bossBar.setVisible(propertyValue.getBoolean());
|
||||
return LazyValue.TRUE;
|
||||
case "remove":
|
||||
bossBarManager.remove(bossBar);
|
||||
return LazyValue.TRUE;
|
||||
default:
|
||||
throw new InternalExpressionException("Unknown bossbar property " + property);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1387,7 +1387,7 @@ public class EntityValue extends Value
|
||||
EntityEventsGroup.Event event = EntityEventsGroup.Event.byName.get(eventName);
|
||||
if (event == null)
|
||||
throw new InternalExpressionException("Unknown entity event: " + eventName);
|
||||
((EntityInterface)entity).getEventContainer().addEvent(event, cc.host.getName(), fun, args);
|
||||
((EntityInterface)entity).getEventContainer().addEvent(event, cc.host, fun, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in new issue
Block a user