rework for events and other stored functions. Fixes #984
This commit is contained in:
1 parent
7ebc990ef6
commit
0e9df3701f
9 files changed
+139
-187
No files matched your search
@@ -815,22 +815,25 @@ In case you want to pass an event handler that is not defined in your module, pl
|
|||||||
|
|
||||||
### `entity_load_handler(descriptor / descriptors, function)`, `entity_load_handler(descriptor / descriptors, call_name, ... args?)`
|
### `entity_load_handler(descriptor / descriptors, function)`, `entity_load_handler(descriptor / descriptors, call_name, ... args?)`
|
||||||
|
|
||||||
Attaches a callback to when any entity matching the following type / types is loaded in the game, allowing to grab a handle
|
Attaches a callback to trigger when any entity matching the following type / types is loaded in the game, allowing to grab a handle
|
||||||
to an entity right when it is loaded to the world without querying them every tick. Callback expects two parameters - the entity,
|
to an entity right when it is loaded to the world without querying them every tick. Callback expects two parameters - the entity,
|
||||||
and a boolean indicating if the entity was newly created(`true`) or just loaded from disk. Single argument functions accepting
|
and a boolean value indicating if the entity was newly created(`true`) or just loaded from disk. Single argument functions accepting
|
||||||
only entities are allowed, but deprecated and will be removed at some point.
|
only entities are allowed, but deprecated and will be removed at some point.
|
||||||
|
|
||||||
If callback is `null`, then the current entity handler, if present, is removed. Consecutive calls to `entity_load_handler` will add / subtract
|
If callback is `null`, then the current entity handler, if present, is removed. Consecutive calls to `entity_load_handler` will add / subtract
|
||||||
of the currently targeted entity types pool.
|
of the currently targeted entity types pool.
|
||||||
|
|
||||||
Like other global events, calls to `entity_load_handler` can only be attached in apps with global scope. Player scope makes so
|
Like other global events, calls to `entity_load_handler` should only be attached in apps with global scope. For player scope apps,
|
||||||
that it is not clear which player to use run the load call.
|
it will be called multiple times, once for each player. That's likely not what you want to do.
|
||||||
|
|
||||||
```
|
```
|
||||||
// veryfast method of getting rid of all the zombies. Callback is so early, its packets haven't reached yet the clients
|
// veryfast method of getting rid of all the zombies. Callback is so early, its packets haven't reached yet the clients
|
||||||
// so to save on log errors, removal of mobs needs to be scheduled for later.
|
// so to save on log errors, removal of mobs needs to be scheduled for later.
|
||||||
entity_load_handler('zombie', _(e, new) -> schedule(0, _(outer(e)) -> modify(e, 'remove')))
|
entity_load_handler('zombie', _(e, new) -> schedule(0, _(outer(e)) -> modify(e, 'remove')))
|
||||||
|
|
||||||
|
// another way to do it is to remove the entity when it starts ticking
|
||||||
|
entity_load_handler('zombie', _(e, new) -> entity_event(e, 'on_tick', _(e) -> modify(e, 'remove')))
|
||||||
|
|
||||||
// making all zombies immediately faster and less susceptible to friction of any sort
|
// making all zombies immediately faster and less susceptible to friction of any sort
|
||||||
entity_load_handler('zombie', _(e, new) -> entity_event(e, 'on_tick', _(e) -> modify(e, 'motion', 1.2*e~'motion')))
|
entity_load_handler('zombie', _(e, new) -> entity_event(e, 'on_tick', _(e) -> modify(e, 'motion', 1.2*e~'motion')))
|
||||||
```
|
```
|
||||||
|
|||||||
+38
-17
@@ -6,11 +6,14 @@ events occur, but app designers can create their own events and trigger them acr
|
|||||||
|
|
||||||
When loading the app, each function that starts
|
When loading the app, each function that starts
|
||||||
with `__on_<event>` and has the required arguments, will be bound automatically to a corresponding built-in event. '`undef`'ying
|
with `__on_<event>` and has the required arguments, will be bound automatically to a corresponding built-in event. '`undef`'ying
|
||||||
of such function would result in unbinding the app from this event.
|
of such function would result in unbinding the app from this event. Defining event hanlder via `__on_<event>(... args) -> expr` is
|
||||||
|
equivalent of defining it via `handle_event('<event>', _(... args) -> expr)`
|
||||||
|
|
||||||
In case of `player` scoped apps,
|
In case of `player` scoped apps,
|
||||||
all player action events will be directed to the appropriate player hosts. Global events, like `'tick'`, that don't have a specific
|
all player action events will be directed to the appropriate player hosts. Global events, like `'tick'`, that don't have a specific
|
||||||
player target will be executed multiple times, once for each player, and once in `'global'` scoped apps.
|
player target will be executed multiple times, once for each player app instance. While each player app instance is independent,
|
||||||
|
statically defined event handlers will be copied to each players app, but if you want to apply them in more controlled way,
|
||||||
|
defining event handlers for each player in `__on_start()` function is preferred.
|
||||||
|
|
||||||
Most built-in events strive to report right before they take an effect in the game. The purpose of that is that this give a choice
|
Most built-in events strive to report right before they take an effect in the game. The purpose of that is that this give a choice
|
||||||
for the programmer to handle them right away (as it happens, potentially affect the course of action by changing the
|
for the programmer to handle them right away (as it happens, potentially affect the course of action by changing the
|
||||||
@@ -21,24 +24,43 @@ more control over these events.
|
|||||||
|
|
||||||
Programmers can also define their own events and signal other events, including built-in events, and across all loaded apps.
|
Programmers can also define their own events and signal other events, including built-in events, and across all loaded apps.
|
||||||
|
|
||||||
## Event list
|
## App scopes and event distribution
|
||||||
|
|
||||||
Here is a list of events that are handled by default in scarpet. This list includes prefixes for function names, allowing apps
|
Events triggered in an app can result in zero, one, or multiple executions, depending on the type of the event, and the app scope.
|
||||||
to autoload them, but you can always add any function to any event (using `/script event` command)
|
* player targeted events (like `player_breaks_block`) target each app once:
|
||||||
if it accepts required number of parameters.
|
* for global scoped apps - targets a single app instance and provides `player` as the first argument.
|
||||||
|
* for player scoped apps - targets only a given player instance, providing player argument for API consistency,
|
||||||
|
since active player in player scoped apps can always be retrived using `player()`.
|
||||||
|
* global events could be handled by multiple players multiple times (like `explosion`, or `tick`):
|
||||||
|
* for global scoped apps - triggered once for the single app instance.
|
||||||
|
* for player scoped apps - triggered N times for each player separately, so they can do something with that information
|
||||||
|
* custom player targeted events (using `signal_event(<event>, <player>, data)`):
|
||||||
|
* for global scoped apps - doesn't trigger at all, since there is no way to pass the required player.
|
||||||
|
To target global apps with player information, use `null` for player target, and add player information to the `data`
|
||||||
|
* for player scoped apps - triggers once for the specified player and its app instance
|
||||||
|
* custom general events (using `signal_event(<event>, null, data)`) behave same like built-in global events:
|
||||||
|
* for global scoped apps - triggers once for the only global instance
|
||||||
|
* for player scoped apps - triggers N times, once for each player app instance
|
||||||
|
|
||||||
|
## Built-in events
|
||||||
|
|
||||||
|
Here is the list of events that are handled by default in scarpet. This list includes prefixes for function names, allowing apps
|
||||||
|
to register them when the app starts, but you can always add any handler function to any event using `/script event` command,
|
||||||
|
if it accepts the required number of parameters for the event.
|
||||||
|
|
||||||
## Meta-events
|
## Meta-events
|
||||||
|
|
||||||
These events are not controlled / triggered by the game per se, but are important for the flow of the apps, however for all
|
These events are not controlled / triggered by the game per se, but are important for the flow of the apps, however for all
|
||||||
intent and purpose can be treated as regular events. Unlike regular events, they cannot be hooked up to with 'handle_event',
|
intent and purpose can be treated as regular events. Unlike regular events, they cannot be hooked up to with `handle_event()`,
|
||||||
but the apps themselves need to have them defined as distinct function definitions, same they cannot be signalled.
|
and the apps themselves need to have them defined as distinct function definitions. They also cannot be triggered via `signal_event()`.
|
||||||
|
|
||||||
### `__on_start()`
|
### `__on_start()`
|
||||||
Called once per app in its logical execution run. For `'global'` scope apps its executed right after the app is loaded. For
|
Called once per app in its logical execution run. For `'global'` scope apps its executed right after the app is loaded. For
|
||||||
`'player'` scope apps, it is triggered once per player before the app can be used by that player. Since each player app acts
|
`'player'` scope apps, it is triggered once per player before the app can be used by that player. Since each player app acts
|
||||||
independently from other player apps, this is probably the best location to include some player specific initializations. Static
|
independently from other player apps, this is probably the best location to include some player specific initializations. Static
|
||||||
code (i.e. code typed directly in the app code that executes immediately, outside of function definitions), will only execute once
|
code (i.e. code typed directly in the app code that executes immediately, outside of function definitions), will only execute once
|
||||||
per app, regardless of scope, `'__on_start()'` allows to reliably call player specific initializations.
|
per app, regardless of scope, `'__on_start()'` allows to reliably call player specific initializations. However, most event handlers
|
||||||
|
defined in the static body of the app will be copied over to each player scoped instance when they join.
|
||||||
|
|
||||||
### `__on_close()`
|
### `__on_close()`
|
||||||
|
|
||||||
@@ -50,8 +72,7 @@ the system is closing down exceptionally.
|
|||||||
## Built-in global events
|
## Built-in global events
|
||||||
|
|
||||||
Global events will be handled once per app that is with `'global'` scope. With `player` scoped apps, each player instance
|
Global events will be handled once per app that is with `'global'` scope. With `player` scoped apps, each player instance
|
||||||
is responsible independently from handling their events, so a global event may be executed multiple times for each player.
|
will be triggerd once for each player, so a global event may be executed multiple times for such apps.
|
||||||
|
|
||||||
|
|
||||||
### `__on_server_starts()`
|
### `__on_server_starts()`
|
||||||
Event triggers after world is loaded and after all startup apps have started. It won't be triggered with `/reload`.
|
Event triggers after world is loaded and after all startup apps have started. It won't be triggered with `/reload`.
|
||||||
@@ -73,13 +94,13 @@ Duplicate of `tick`, just automatically located in the end. Use `__on_tick() ->
|
|||||||
### `__on_chunk_generated(x, z)`
|
### `__on_chunk_generated(x, z)`
|
||||||
Called right after a chunk at a given coordinate is full generated. `x` and `z` correspond
|
Called right after a chunk at a given coordinate is full generated. `x` and `z` correspond
|
||||||
to the lowest x and z coords in the chunk. Handling of this event is scheduled as an off-tick task happening after the
|
to the lowest x and z coords in the chunk. Handling of this event is scheduled as an off-tick task happening after the
|
||||||
chunk is confirmed to be generated and loaded to the game, so
|
chunk is confirmed to be generated and loaded to the game, due to the off-thread chunk loading in the game. So
|
||||||
handling of this event is not technically guaranteed, if the game crashes while players are moving for example, and can
|
handling of this event is not technically guaranteed if the game crashes while players are moving for example, and the game
|
||||||
be missed on the next start, if the game successfully saves it and fails to execute all remaining tasks. In normal operation
|
decides to shut down after chunk is fully loaded and before its handler is processed in between ticks. In normal operation
|
||||||
this should not happen, but be warned.
|
this should not happen, but let you be warned.
|
||||||
|
|
||||||
### `__on_chunk_loaded(x, z)`
|
### `__on_chunk_loaded(x, z)`
|
||||||
Called right after a chunk at a given coordinate is loaded. All newly generated chunks are loaded as well.
|
Called right after a chunk at a given coordinate is loaded. All newly generated chunks are considered loaded as well.
|
||||||
`x` and `z` correspond to the lowest x and z coordinates in the chunk.
|
`x` and `z` correspond to the lowest x and z coordinates in the chunk.
|
||||||
|
|
||||||
### `__on_lightning(block, mode)`
|
### `__on_lightning(block, mode)`
|
||||||
@@ -103,7 +124,7 @@ The parameter `entities` contains the list of entities that have been affected b
|
|||||||
Triggered when a carpet mod rule is changed. It includes extension rules, not using default `/carpet` command,
|
Triggered when a carpet mod rule is changed. It includes extension rules, not using default `/carpet` command,
|
||||||
which will then be namespaced as `namespace:rule`.
|
which will then be namespaced as `namespace:rule`.
|
||||||
|
|
||||||
### entity load event -> check `entity_load_handler()`
|
### Entity load event -> check in details on `entity_load_handler()`
|
||||||
|
|
||||||
These will trigger every time an entity of a given type is loaded into the game: spawned, added with a chunks,
|
These will trigger every time an entity of a given type is loaded into the game: spawned, added with a chunks,
|
||||||
spawned from commands, anything really. Check `entity_load_handler()` in the entity section for details.
|
spawned from commands, anything really. Check `entity_load_handler()` in the entity section for details.
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public abstract class ArmorStandEntity_scarpetMarkerMixin extends LivingEntity
|
|||||||
if (owner.isPresent())
|
if (owner.isPresent())
|
||||||
{
|
{
|
||||||
String hostName = StringUtils.removeStart(owner.get(),prefix);
|
String hostName = StringUtils.removeStart(owner.get(),prefix);
|
||||||
if (!hostName.isEmpty() && CarpetServer.scriptServer.getHostByName(hostName) == null)
|
if (!hostName.isEmpty() && CarpetServer.scriptServer.getAppHostByName(hostName) == null)
|
||||||
{
|
{
|
||||||
discard(); //discard
|
discard(); //discard
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package carpet.script;
|
|||||||
import carpet.CarpetServer;
|
import carpet.CarpetServer;
|
||||||
import carpet.CarpetSettings;
|
import carpet.CarpetSettings;
|
||||||
import carpet.helpers.TickSpeed;
|
import carpet.helpers.TickSpeed;
|
||||||
|
import carpet.script.exception.IntegrityException;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
|
import carpet.script.exception.InvalidCallbackException;
|
||||||
import carpet.script.value.BlockValue;
|
import carpet.script.value.BlockValue;
|
||||||
import carpet.script.value.BooleanValue;
|
import carpet.script.value.BooleanValue;
|
||||||
import carpet.script.value.EntityValue;
|
import carpet.script.value.EntityValue;
|
||||||
@@ -25,7 +27,6 @@ import net.minecraft.entity.TntEntity;
|
|||||||
import net.minecraft.entity.damage.DamageSource;
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
import net.minecraft.entity.passive.MerchantEntity;
|
import net.minecraft.entity.passive.MerchantEntity;
|
||||||
import net.minecraft.entity.projectile.ProjectileEntity;
|
import net.minecraft.entity.projectile.ProjectileEntity;
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
@@ -46,7 +47,6 @@ import net.minecraft.village.Merchant;
|
|||||||
import net.minecraft.village.TradeOffer;
|
import net.minecraft.village.TradeOffer;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.explosion.Explosion;
|
import net.minecraft.world.explosion.Explosion;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -70,10 +70,17 @@ import java.util.stream.Collectors;
|
|||||||
public class CarpetEventServer
|
public class CarpetEventServer
|
||||||
{
|
{
|
||||||
public final List<ScheduledCall> scheduledCalls = new LinkedList<>();
|
public final List<ScheduledCall> scheduledCalls = new LinkedList<>();
|
||||||
public final MinecraftServer server;
|
public final CarpetScriptServer scriptServer;
|
||||||
private static final List<Value> NOARGS = Collections.emptyList();
|
private static final List<Value> NOARGS = Collections.emptyList();
|
||||||
public final Map<String, Event> customEvents = new HashMap<>();
|
public final Map<String, Event> customEvents = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public enum CallbackResult
|
||||||
|
{
|
||||||
|
SUCCESS, PASS, FAIL
|
||||||
|
}
|
||||||
|
|
||||||
public static class Callback
|
public static class Callback
|
||||||
{
|
{
|
||||||
public final String host;
|
public final String host;
|
||||||
@@ -81,7 +88,6 @@ public class CarpetEventServer
|
|||||||
public final FunctionValue function;
|
public final FunctionValue function;
|
||||||
public final List<Value> parametrizedArgs;
|
public final List<Value> parametrizedArgs;
|
||||||
|
|
||||||
|
|
||||||
public Callback(String host, String target, FunctionValue function, List<Value> parametrizedArgs)
|
public Callback(String host, String target, FunctionValue function, List<Value> parametrizedArgs)
|
||||||
{
|
{
|
||||||
this.host = host;
|
this.host = host;
|
||||||
@@ -95,18 +101,17 @@ public class CarpetEventServer
|
|||||||
* @param sender - entity command source
|
* @param sender - entity command source
|
||||||
* @param runtimeArgs = options
|
* @param runtimeArgs = options
|
||||||
*/
|
*/
|
||||||
public boolean execute(ServerCommandSource sender, List<Value> runtimeArgs)
|
public CallbackResult execute(ServerCommandSource sender, List<Value> runtimeArgs)
|
||||||
{
|
{
|
||||||
if (!this.parametrizedArgs.isEmpty())
|
if (!this.parametrizedArgs.isEmpty())
|
||||||
{
|
{
|
||||||
runtimeArgs = new ArrayList<>(runtimeArgs);
|
runtimeArgs = new ArrayList<>(runtimeArgs);
|
||||||
runtimeArgs.addAll(this.parametrizedArgs);
|
runtimeArgs.addAll(this.parametrizedArgs);
|
||||||
}
|
}
|
||||||
if (CarpetServer.scriptServer == null) return false; // already stopped
|
if (CarpetServer.scriptServer == null) return CallbackResult.FAIL; // already stopped
|
||||||
return CarpetServer.scriptServer.runEventCall(
|
return CarpetServer.scriptServer.events.runEventCall(
|
||||||
sender.withLevel(CarpetSettings.runPermissionLevel),
|
sender.withLevel(CarpetSettings.runPermissionLevel),
|
||||||
host, optionalTarget, function, runtimeArgs
|
host, optionalTarget, function, runtimeArgs);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,18 +120,12 @@ public class CarpetEventServer
|
|||||||
* @param optionalRecipient - optional target player argument
|
* @param optionalRecipient - optional target player argument
|
||||||
* @param runtimeArgs = options
|
* @param runtimeArgs = options
|
||||||
*/
|
*/
|
||||||
public int signal(ServerCommandSource sender, ServerPlayerEntity optionalRecipient, List<Value> runtimeArgs)
|
public CallbackResult signal(ServerCommandSource sender, ServerPlayerEntity optionalRecipient, List<Value> runtimeArgs)
|
||||||
{
|
{
|
||||||
// recipent of the call doesn't match the handlingHost
|
// recipent of the call doesn't match the handlingHost
|
||||||
if (optionalRecipient != null && !optionalRecipient.getEntityName().equals(optionalTarget))
|
if (optionalRecipient != null && !optionalRecipient.getEntityName().equals(optionalTarget))
|
||||||
return 0;
|
return CallbackResult.FAIL;
|
||||||
List<Value> args = runtimeArgs;
|
return execute(sender, runtimeArgs);
|
||||||
if (!this.parametrizedArgs.isEmpty())
|
|
||||||
{
|
|
||||||
args = new ArrayList<>(runtimeArgs);
|
|
||||||
args.addAll(this.parametrizedArgs);
|
|
||||||
}
|
|
||||||
return CarpetServer.scriptServer.signal(sender, optionalRecipient, host, function, args, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -178,10 +177,8 @@ public class CarpetEventServer
|
|||||||
*/
|
*/
|
||||||
public void execute()
|
public void execute()
|
||||||
{
|
{
|
||||||
CarpetServer.scriptServer.runScheduledCall(ctx.origin, ctx.s, host, (CarpetScriptHost) ctx.host, function, parametrizedArgs);
|
CarpetServer.scriptServer.events.runScheduledCall(ctx.origin, ctx.s, host, (CarpetScriptHost) ctx.host, function, parametrizedArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CallbackList
|
public static class CallbackList
|
||||||
@@ -190,7 +187,6 @@ public class CarpetEventServer
|
|||||||
public final List<Callback> callList;
|
public final List<Callback> callList;
|
||||||
public final int reqArgs;
|
public final int reqArgs;
|
||||||
final boolean isSystem;
|
final boolean isSystem;
|
||||||
final boolean isGlobalOnly;
|
|
||||||
final boolean perPlayerDistribution;
|
final boolean perPlayerDistribution;
|
||||||
|
|
||||||
public CallbackList(int reqArgs, boolean isSystem, boolean isGlobalOnly)
|
public CallbackList(int reqArgs, boolean isSystem, boolean isGlobalOnly)
|
||||||
@@ -198,7 +194,6 @@ public class CarpetEventServer
|
|||||||
this.callList = new ArrayList<>();
|
this.callList = new ArrayList<>();
|
||||||
this.reqArgs = reqArgs;
|
this.reqArgs = reqArgs;
|
||||||
this.isSystem = isSystem;
|
this.isSystem = isSystem;
|
||||||
this.isGlobalOnly = isGlobalOnly;
|
|
||||||
perPlayerDistribution = isSystem && !isGlobalOnly;
|
perPlayerDistribution = isSystem && !isGlobalOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +225,7 @@ public class CarpetEventServer
|
|||||||
// supressing calls where target player hosts simply don't match
|
// supressing calls where target player hosts simply don't match
|
||||||
// handling global hosts with player targets is left to when the host is resolved (few calls deeper).
|
// handling global hosts with player targets is left to when the host is resolved (few calls deeper).
|
||||||
if (nameCheck != null && call.optionalTarget != null && !nameCheck.equals(call.optionalTarget)) continue;
|
if (nameCheck != null && call.optionalTarget != null && !nameCheck.equals(call.optionalTarget)) continue;
|
||||||
if (!call.execute(source, argv)) fails.add(call);
|
if (call.execute(source, argv) == CallbackResult.FAIL) fails.add(call);
|
||||||
}
|
}
|
||||||
for (Callback call : fails) callList.remove(call);
|
for (Callback call : fails) callList.remove(call);
|
||||||
CarpetProfiler.end_current_section(currentSection);
|
CarpetProfiler.end_current_section(currentSection);
|
||||||
@@ -245,7 +240,9 @@ public class CarpetEventServer
|
|||||||
int successes = 0;
|
int successes = 0;
|
||||||
for (Callback call: callList)
|
for (Callback call: callList)
|
||||||
{
|
{
|
||||||
successes += Math.max(0, call.signal(sender, optinoalReceipient, callArg));
|
//successes += Math.max(0, call.signal(sender, optinoalReceipient, callArg));
|
||||||
|
if (call.signal(sender, optinoalReceipient, callArg) == CallbackResult.SUCCESS) successes ++;
|
||||||
|
|
||||||
}
|
}
|
||||||
//for (Callback call : fails) callList.remove(call);
|
//for (Callback call : fails) callList.remove(call);
|
||||||
return successes;
|
return successes;
|
||||||
@@ -253,7 +250,7 @@ public class CarpetEventServer
|
|||||||
|
|
||||||
public boolean addFromExternal(ServerCommandSource source, String hostName, String funName, Consumer<ScriptHost> hostOnEventHandler)
|
public boolean addFromExternal(ServerCommandSource source, String hostName, String funName, Consumer<ScriptHost> hostOnEventHandler)
|
||||||
{
|
{
|
||||||
ScriptHost host = CarpetServer.scriptServer.getHostByName(hostName);
|
ScriptHost host = CarpetServer.scriptServer.getAppHostByName(hostName);
|
||||||
if (host == null)
|
if (host == null)
|
||||||
{
|
{
|
||||||
// impossible call to add
|
// impossible call to add
|
||||||
@@ -991,8 +988,6 @@ public class CarpetEventServer
|
|||||||
public final String name;
|
public final String name;
|
||||||
|
|
||||||
public final CallbackList handler;
|
public final CallbackList handler;
|
||||||
@Deprecated
|
|
||||||
public final boolean globalOnly;
|
|
||||||
public final boolean isPublic; // public events can be targetted with __on_<event> defs
|
public final boolean isPublic; // public events can be targetted with __on_<event> defs
|
||||||
public Event(String name, int reqArgs, boolean isGlobalOnly)
|
public Event(String name, int reqArgs, boolean isGlobalOnly)
|
||||||
{
|
{
|
||||||
@@ -1002,7 +997,6 @@ public class CarpetEventServer
|
|||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.handler = new CallbackList(reqArgs, true, isGlobalOnly);
|
this.handler = new CallbackList(reqArgs, true, isGlobalOnly);
|
||||||
this.globalOnly = isGlobalOnly;
|
|
||||||
this.isPublic = isPublic;
|
this.isPublic = isPublic;
|
||||||
byName.put(name, this);
|
byName.put(name, this);
|
||||||
}
|
}
|
||||||
@@ -1050,7 +1044,6 @@ public class CarpetEventServer
|
|||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.handler = new CallbackList(1, false, false);
|
this.handler = new CallbackList(1, false, false);
|
||||||
this.globalOnly = false;
|
|
||||||
this.isPublic = true;
|
this.isPublic = true;
|
||||||
server.events.customEvents.put(name, this);
|
server.events.customEvents.put(name, this);
|
||||||
}
|
}
|
||||||
@@ -1122,9 +1115,9 @@ public class CarpetEventServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public CarpetEventServer(MinecraftServer server)
|
public CarpetEventServer(CarpetScriptServer scriptServer)
|
||||||
{
|
{
|
||||||
this.server = server;
|
this.scriptServer = scriptServer;
|
||||||
Event.clearAllBuiltinEvents();
|
Event.clearAllBuiltinEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1155,6 +1148,45 @@ public class CarpetEventServer
|
|||||||
scheduledCalls.add(new ScheduledCall(context, function, args, due));
|
scheduledCalls.add(new ScheduledCall(context, function, args, due));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void runScheduledCall(BlockPos origin, ServerCommandSource source, String hostname, CarpetScriptHost host, FunctionValue udf, List<Value> argv)
|
||||||
|
{
|
||||||
|
if (hostname != null && !scriptServer.modules.containsKey(hostname)) // well - scheduled call app got unloaded
|
||||||
|
return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
host.callUDF(origin, source, udf, argv);
|
||||||
|
}
|
||||||
|
catch (NullPointerException | InvalidCallbackException | IntegrityException ignored) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public CallbackResult runEventCall(ServerCommandSource sender, String hostname, String optionalTarget, FunctionValue udf, List<Value> argv)
|
||||||
|
{
|
||||||
|
CarpetScriptHost appHost = scriptServer.getAppHostByName(hostname);
|
||||||
|
// no such app
|
||||||
|
if (appHost == null) return CallbackResult.FAIL;
|
||||||
|
// dummy call for player apps that reside on the global copy - do not run them, but report as passes.
|
||||||
|
if (appHost.isPerUser() && optionalTarget==null) return CallbackResult.PASS;
|
||||||
|
ServerPlayerEntity target = null;
|
||||||
|
if (optionalTarget != null)
|
||||||
|
{
|
||||||
|
target = sender.getServer().getPlayerManager().getPlayer(optionalTarget);
|
||||||
|
if (target == null) return CallbackResult.FAIL;
|
||||||
|
}
|
||||||
|
ServerCommandSource source = sender.withLevel(CarpetSettings.runPermissionLevel);
|
||||||
|
CarpetScriptHost executingHost = appHost.retrieveForExecution(sender, target);
|
||||||
|
if (executingHost == null) return CallbackResult.FAIL;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
executingHost.callUDF(BlockPos.ORIGIN, source.withLevel(CarpetSettings.runPermissionLevel), udf, argv);
|
||||||
|
return CallbackResult.SUCCESS;
|
||||||
|
}
|
||||||
|
catch (NullPointerException | InvalidCallbackException | IntegrityException error)
|
||||||
|
{
|
||||||
|
CarpetScriptServer.LOG.error("Got exception: "+error.getMessage());
|
||||||
|
return CallbackResult.FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean addEventFromCommand(ServerCommandSource source, String event, String host, String funName)
|
public boolean addEventFromCommand(ServerCommandSource source, String event, String host, String funName)
|
||||||
{
|
{
|
||||||
Event ev = Event.getEvent(event, CarpetServer.scriptServer);
|
Event ev = Event.getEvent(event, CarpetServer.scriptServer);
|
||||||
@@ -1178,7 +1210,7 @@ public class CarpetEventServer
|
|||||||
|
|
||||||
public boolean handleCustomEvent(String event, CarpetScriptHost host, FunctionValue function, List<Value> args)
|
public boolean handleCustomEvent(String event, CarpetScriptHost host, FunctionValue function, List<Value> args)
|
||||||
{
|
{
|
||||||
Event ev = Event.getOrCreateCustom(event, host.getScriptServer());
|
Event ev = Event.getOrCreateCustom(event, scriptServer);
|
||||||
onEventAddedToHost(ev, host);
|
onEventAddedToHost(ev, host);
|
||||||
return ev.handler.addEventCallInternal(host, function, args==null?NOARGS:args);
|
return ev.handler.addEventCallInternal(host, function, args==null?NOARGS:args);
|
||||||
}
|
}
|
||||||
@@ -1233,15 +1265,4 @@ public class CarpetEventServer
|
|||||||
// remove scheduled calls
|
// remove scheduled calls
|
||||||
scheduledCalls.removeIf(sc -> sc.host != null && sc.host.equals(host.getName()));
|
scheduledCalls.removeIf(sc -> sc.host != null && sc.host.equals(host.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pair<String,String> decodeCallback(String funName)
|
|
||||||
{
|
|
||||||
Pattern find = Pattern.compile("(\\w+)\\(from (\\w+)\\)");
|
|
||||||
Matcher matcher = find.matcher(funName);
|
|
||||||
if(matcher.matches())
|
|
||||||
{
|
|
||||||
return Pair.of(matcher.group(2), matcher.group(1));
|
|
||||||
}
|
|
||||||
return Pair.of(null, funName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ import carpet.script.command.CommandArgument;
|
|||||||
import carpet.script.command.CommandToken;
|
import carpet.script.command.CommandToken;
|
||||||
import carpet.script.exception.CarpetExpressionException;
|
import carpet.script.exception.CarpetExpressionException;
|
||||||
import carpet.script.exception.ExpressionException;
|
import carpet.script.exception.ExpressionException;
|
||||||
|
import carpet.script.exception.IntegrityException;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
import carpet.script.exception.InvalidCallbackException;
|
import carpet.script.exception.InvalidCallbackException;
|
||||||
import carpet.script.utils.AppStoreManager;
|
import carpet.script.utils.AppStoreManager;
|
||||||
@@ -644,37 +645,19 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<CarpetScriptHost> retrieveForExecution(ServerCommandSource source, String optionalTarget)
|
public CarpetScriptHost retrieveForExecution(ServerCommandSource source, ServerPlayerEntity player)
|
||||||
{
|
{
|
||||||
List<CarpetScriptHost> targets = new ArrayList<>();
|
CarpetScriptHost target = null;
|
||||||
if (perUser)
|
if (!perUser)
|
||||||
{
|
{
|
||||||
if (optionalTarget == null)
|
target = this;
|
||||||
{
|
|
||||||
for (ServerPlayerEntity player : source.getServer().getPlayerManager().getPlayerList())
|
|
||||||
{
|
|
||||||
CarpetScriptHost host = (CarpetScriptHost) retrieveForExecution(player.getEntityName());
|
|
||||||
targets.add(host);
|
|
||||||
if (host.errorSnooper == null) host.setChatErrorSnooper(player.getCommandSource());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ServerPlayerEntity player = source.getServer().getPlayerManager().getPlayer(optionalTarget);
|
|
||||||
if (player != null)
|
|
||||||
{
|
|
||||||
CarpetScriptHost host = (CarpetScriptHost) retrieveForExecution(player.getEntityName());
|
|
||||||
targets.add(host);
|
|
||||||
if (host.errorSnooper == null) host.setChatErrorSnooper(player.getCommandSource());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else if (player != null)
|
||||||
{
|
{
|
||||||
targets.add(this);
|
target = (CarpetScriptHost) retrieveForExecution(player.getEntityName());
|
||||||
if (this.errorSnooper == null) this.setChatErrorSnooper(source);
|
|
||||||
}
|
}
|
||||||
return targets;
|
if (target != null && target.errorSnooper == null) target.setChatErrorSnooper(source);
|
||||||
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CarpetScriptHost retrieveOwnForExecution(ServerCommandSource source) throws CommandSyntaxException
|
public CarpetScriptHost retrieveOwnForExecution(ServerCommandSource source) throws CommandSyntaxException
|
||||||
@@ -830,6 +813,7 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// TODO: this is just for now - invoke would be able to invoke other hosts scripts
|
// TODO: this is just for now - invoke would be able to invoke other hosts scripts
|
||||||
|
assertAppIntegrity(function.getModule());
|
||||||
Context context = new CarpetContext(this, source, BlockPos.ORIGIN);
|
Context context = new CarpetContext(this, source, BlockPos.ORIGIN);
|
||||||
return function.getExpression().evalValue(
|
return function.getExpression().evalValue(
|
||||||
() -> function.lazyEval(context, Context.VOID, function.getExpression(), function.getToken(), argv),
|
() -> function.lazyEval(context, Context.VOID, function.getExpression(), function.getToken(), argv),
|
||||||
@@ -860,7 +844,7 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// TODO: this is just for now - invoke would be able to invoke other hosts scripts
|
assertAppIntegrity(function.getModule());
|
||||||
Context context = new CarpetContext(this, source, BlockPos.ORIGIN);
|
Context context = new CarpetContext(this, source, BlockPos.ORIGIN);
|
||||||
return function.getExpression().evalValue(
|
return function.getExpression().evalValue(
|
||||||
() -> function.execute(context, Context.VOID, function.getExpression(), function.getToken(), argv),
|
() -> function.execute(context, Context.VOID, function.getExpression(), function.getToken(), argv),
|
||||||
@@ -874,7 +858,7 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Value callUDF(BlockPos pos, ServerCommandSource source, FunctionValue fun, List<Value> argv) throws InvalidCallbackException
|
public Value callUDF(BlockPos pos, ServerCommandSource source, FunctionValue fun, List<Value> argv) throws InvalidCallbackException, IntegrityException
|
||||||
{
|
{
|
||||||
if (CarpetServer.scriptServer.stopAll)
|
if (CarpetServer.scriptServer.stopAll)
|
||||||
return Value.NULL;
|
return Value.NULL;
|
||||||
@@ -889,7 +873,7 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// TODO: this is just for now - invoke would be able to invoke other hosts scripts
|
assertAppIntegrity(fun.getModule());
|
||||||
Context context = new CarpetContext(this, source, pos);
|
Context context = new CarpetContext(this, source, pos);
|
||||||
return fun.getExpression().evalValue(
|
return fun.getExpression().evalValue(
|
||||||
() -> fun.execute(context, Context.VOID, fun.getExpression(), fun.getToken(), argv),
|
() -> fun.execute(context, Context.VOID, fun.getExpression(), fun.getToken(), argv),
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ import carpet.script.bundled.BundledModule;
|
|||||||
import carpet.CarpetServer;
|
import carpet.CarpetServer;
|
||||||
import carpet.script.bundled.FileModule;
|
import carpet.script.bundled.FileModule;
|
||||||
import carpet.script.bundled.Module;
|
import carpet.script.bundled.Module;
|
||||||
import carpet.script.exception.IntegrityException;
|
|
||||||
import carpet.script.exception.InvalidCallbackException;
|
|
||||||
import carpet.script.language.Arithmetic;
|
import carpet.script.language.Arithmetic;
|
||||||
import carpet.script.language.ControlFlow;
|
import carpet.script.language.ControlFlow;
|
||||||
import carpet.script.language.DataStructures;
|
import carpet.script.language.DataStructures;
|
||||||
@@ -23,7 +21,6 @@ import carpet.script.language.Sys;
|
|||||||
import carpet.script.language.Threading;
|
import carpet.script.language.Threading;
|
||||||
import carpet.script.utils.AppStoreManager;
|
import carpet.script.utils.AppStoreManager;
|
||||||
import carpet.script.value.FunctionValue;
|
import carpet.script.value.FunctionValue;
|
||||||
import carpet.script.value.Value;
|
|
||||||
import carpet.utils.CarpetProfiler;
|
import carpet.utils.CarpetProfiler;
|
||||||
import carpet.utils.Messenger;
|
import carpet.utils.Messenger;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
@@ -35,7 +32,6 @@ import net.minecraft.server.MinecraftServer;
|
|||||||
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.WorldSavePath;
|
import net.minecraft.util.WorldSavePath;
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
@@ -120,9 +116,9 @@ public class CarpetScriptServer
|
|||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
ScriptHost.systemGlobals.clear();
|
ScriptHost.systemGlobals.clear();
|
||||||
events = new CarpetEventServer(server);
|
events = new CarpetEventServer(this);
|
||||||
modules = new HashMap<>();
|
modules = new HashMap<>();
|
||||||
unloadableModules = new HashSet<String>();
|
unloadableModules = new HashSet<>();
|
||||||
tickStart = 0L;
|
tickStart = 0L;
|
||||||
stopAll = false;
|
stopAll = false;
|
||||||
holyMoly = server.getCommandManager().getDispatcher().getRoot().getChildren().stream().map(CommandNode::getName).collect(Collectors.toSet());
|
holyMoly = server.getCommandManager().getDispatcher().getRoot().getChildren().stream().map(CommandNode::getName).collect(Collectors.toSet());
|
||||||
@@ -232,7 +228,7 @@ public class CarpetScriptServer
|
|||||||
return moduleNames;
|
return moduleNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptHost getHostByName(String name)
|
public CarpetScriptHost getAppHostByName(String name)
|
||||||
{
|
{
|
||||||
if (name == null)
|
if (name == null)
|
||||||
return globalHost;
|
return globalHost;
|
||||||
@@ -310,7 +306,10 @@ public class CarpetScriptServer
|
|||||||
if (newHost.isPerUser())
|
if (newHost.isPerUser())
|
||||||
{
|
{
|
||||||
// that will provide player hosts right at the startup
|
// that will provide player hosts right at the startup
|
||||||
newHost.retrieveForExecution(source, null);
|
for (ServerPlayerEntity player : source.getServer().getPlayerManager().getPlayerList())
|
||||||
|
{
|
||||||
|
newHost.retrieveForExecution(player.getCommandSource(), player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -372,86 +371,6 @@ public class CarpetScriptServer
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean runEventCall(ServerCommandSource sender, String hostname, String optionalTarget, FunctionValue udf, List<Value> argv)
|
|
||||||
{
|
|
||||||
CarpetScriptHost host = globalHost;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
target = sender.getServer().getPlayerManager().getPlayer(optionalTarget);
|
|
||||||
if (target == null) return false;
|
|
||||||
}
|
|
||||||
int successes = signal(sender, target, hostname, udf, argv, true );
|
|
||||||
return successes >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (hostname == null)
|
|
||||||
{
|
|
||||||
if (optionalRecipient != null) return 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
globalHost.callUDF(BlockPos.ORIGIN, sender, udf, argv);
|
|
||||||
}
|
|
||||||
catch (NullPointerException | InvalidCallbackException npe)
|
|
||||||
{
|
|
||||||
return reportFails?-1:0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
// getPlayer will always return nonnull cause retrieve for execution only returns hosts for existing players.
|
|
||||||
ServerCommandSource executingSource = host.perUser
|
|
||||||
? source.getServer().getPlayerManager().getPlayer(host.user).getCommandSource()
|
|
||||||
: source.getServer().getCommandSource();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
host.callUDF(BlockPos.ORIGIN, source.withLevel(CarpetSettings.runPermissionLevel), udf, argv);
|
|
||||||
}
|
|
||||||
catch (NullPointerException | InvalidCallbackException | IntegrityException npe)
|
|
||||||
{
|
|
||||||
if (reportFails) return -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
successes ++;
|
|
||||||
}
|
|
||||||
return successes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tick()
|
public void tick()
|
||||||
{
|
{
|
||||||
CarpetProfiler.ProfilerToken token;
|
CarpetProfiler.ProfilerToken token;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class EntityEventsGroup
|
|||||||
{
|
{
|
||||||
Map.Entry<Pair<String,String>, CarpetEventServer.Callback> action = iterator.next();
|
Map.Entry<Pair<String,String>, CarpetEventServer.Callback> action = iterator.next();
|
||||||
Pair<String,String> key = action.getKey();
|
Pair<String,String> key = action.getKey();
|
||||||
ScriptHost host = CarpetServer.scriptServer.getHostByName(key.getLeft());
|
ScriptHost host = CarpetServer.scriptServer.getAppHostByName(key.getLeft());
|
||||||
if (host == null)
|
if (host == null)
|
||||||
{
|
{
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
@@ -52,7 +52,7 @@ public class EntityEventsGroup
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!type.call(action.getValue(), entity, args))
|
if (type.call(action.getValue(), entity, args) == CarpetEventServer.CallbackResult.FAIL)
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
if (actionSet.isEmpty()) actions.remove(type);
|
if (actionSet.isEmpty()) actions.remove(type);
|
||||||
@@ -125,7 +125,7 @@ public class EntityEventsGroup
|
|||||||
}
|
}
|
||||||
return new CarpetEventServer.Callback(key.getLeft(), key.getRight(), function, extraArgs);
|
return new CarpetEventServer.Callback(key.getLeft(), key.getRight(), function, extraArgs);
|
||||||
}
|
}
|
||||||
public boolean call(CarpetEventServer.Callback tickCall, Entity entity, Object ... args)
|
public CarpetEventServer.CallbackResult call(CarpetEventServer.Callback tickCall, Entity entity, Object ... args)
|
||||||
{
|
{
|
||||||
assert args.length == argcount-1;
|
assert args.length == argcount-1;
|
||||||
return tickCall.execute(entity.getCommandSource(), makeArgs(entity, args));
|
return tickCall.execute(entity.getCommandSource(), makeArgs(entity, args));
|
||||||
|
|||||||
@@ -305,6 +305,11 @@ public abstract class ScriptHost
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void assertAppIntegrity(Module module)
|
||||||
|
{
|
||||||
|
getModuleData(module);
|
||||||
|
}
|
||||||
|
|
||||||
public void addUserDefinedFunction(Context ctx, Module module, String name, FunctionValue fun)
|
public void addUserDefinedFunction(Context ctx, Module module, String name, FunctionValue fun)
|
||||||
{
|
{
|
||||||
getModuleData(module).globalFunctions.put(name, fun);
|
getModuleData(module).globalFunctions.put(name, fun);
|
||||||
|
|||||||
@@ -262,7 +262,6 @@ public class Entities {
|
|||||||
|
|
||||||
expression.addContextFunction("entity_load_handler", -1, (c, t, lv) ->
|
expression.addContextFunction("entity_load_handler", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
if (c.host.isPerUser()) throw new InternalExpressionException("'entity_load_handler' can only be called in apps with global scope");
|
|
||||||
if (lv.size() < 2) throw new InternalExpressionException("'entity_load_handler' required the entity type, and a function to call");
|
if (lv.size() < 2) throw new InternalExpressionException("'entity_load_handler' required the entity type, and a function to call");
|
||||||
Value entityValue = lv.get(0);
|
Value entityValue = lv.get(0);
|
||||||
List<String> descriptors = (entityValue instanceof ListValue)
|
List<String> descriptors = (entityValue instanceof ListValue)
|
||||||
|
|||||||
Reference in new issue
Block a user