added __on_start and defined better meta-events
This commit is contained in:
1 parent
0a45778e4a
commit
4c09d6b736
8 files changed
+86
-22
No files matched your search
@@ -27,11 +27,32 @@ Here is a list of events that are handled by default in scarpet. This list inclu
|
||||
to autoload them, but you can always add any function to any event (using `/script event` command)
|
||||
if it accepts required number of parameters.
|
||||
|
||||
## 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
|
||||
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.
|
||||
|
||||
### `__on_start()`
|
||||
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
|
||||
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
|
||||
per app, regardless of scope, `'__on_start()'` allows to reliably call player specific initializations.
|
||||
|
||||
### `__on_close()`
|
||||
|
||||
Called once per app when the app is closing or reloading, right before the app is removed.
|
||||
For player scoped apps, its called once per player. Scarpet app engine will attempt to call `'__on_close()'` even if
|
||||
the system is closing down exceptionally.
|
||||
|
||||
|
||||
## Built-in global events
|
||||
|
||||
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.
|
||||
|
||||
|
||||
### `__on_server_starts()`
|
||||
Event triggers after world is loaded and after all startup apps have started. It won't be triggered with `/reload`.
|
||||
|
||||
|
||||
@@ -13,6 +13,11 @@ When loaded (via `/script load` command, etc.), the game will run the content of
|
||||
`__config()` function, if present, which will be executed once. Loading the app will also bind specific
|
||||
events to the event system (check Events section for details).
|
||||
|
||||
If an app defines `__on_start()` function, it will be executed once before running anything else. For global scoped apps,
|
||||
this is just after they are loaded, and for player scoped apps, before they are used first time by a player.
|
||||
Unlike static code (written directly in the body of the app code), that always run once per app, this may run multiple times if
|
||||
its a player app nd multiple players are on the server.
|
||||
|
||||
Unloading an app removes all of its state from the game, disables commands, removes bounded events, and
|
||||
saves its global state. If more cleanup is needed, one can define `__on_close()` function which will be
|
||||
executed when the module is unloaded, or server is closing or crashing. However, there is no need to do that
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
__command() ->
|
||||
__config() ->
|
||||
__on_chunk_generated(x, z) ->
|
||||
__on_close() ->
|
||||
__on_chunk_generated(x, z) ->
|
||||
__on_close() ->
|
||||
__on_player_attacks_entity(player, entity) ->
|
||||
__on_player_breaks_block(player, block) ->
|
||||
__on_player_clicks_block(player, block, face) ->
|
||||
@@ -25,14 +25,15 @@ __on_player_starts_sprinting(player) ->
|
||||
__on_player_stops_sneaking(player) ->
|
||||
__on_player_stops_sprinting(player) ->
|
||||
__on_player_swings_hand(player, hand) ->
|
||||
__on_player_switches_slot(player, from, to) ->
|
||||
__on_player_switches_slot(player, from, to) ->
|
||||
__on_player_swaps_hands(player) ->
|
||||
__on_player_takes_damage(player, amount, source, entity) ->
|
||||
__on_player_trades(player, entity, buy_left, buy_right, sell) ->
|
||||
__on_player_uses_item(player, item_tuple, hand) ->
|
||||
__on_player_wakes_up(player) ->
|
||||
__on_player_escapes_sleep(player) ->
|
||||
__on_statistic(player, category, event, value) ->
|
||||
__on_statistic(player, category, event, value) ->
|
||||
__on_start() ->
|
||||
__on_tick() ->
|
||||
__on_tick_ender() ->
|
||||
__on_tick_nether() ->
|
||||
|
||||
@@ -129,6 +129,7 @@
|
||||
__on_player_wakes_up
|
||||
__on_player_escapes_sleep
|
||||
__on_statistic
|
||||
__on_start
|
||||
__on_tick
|
||||
__on_tick_ender
|
||||
__on_tick_nether
|
||||
|
||||
@@ -88,7 +88,7 @@ public class CarpetScriptHost extends ScriptHost
|
||||
|
||||
public static CarpetScriptHost create(CarpetScriptServer scriptServer, Module module, boolean perPlayer, ServerCommandSource source, Function<ServerCommandSource, Boolean> commandValidator, boolean isRuleApp)
|
||||
{
|
||||
CarpetScriptHost host = new CarpetScriptHost(scriptServer, module, perPlayer, null, Collections.emptyMap(), new HashMap<>(), commandValidator, isRuleApp);
|
||||
CarpetScriptHost host = new CarpetScriptHost(scriptServer, module, perPlayer, null, Collections.emptyMap(), new HashMap<>(), commandValidator, isRuleApp);
|
||||
// parse code and convert to expression
|
||||
if (module != null)
|
||||
{
|
||||
@@ -227,11 +227,14 @@ public class CarpetScriptHost extends ScriptHost
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void transferToChild(ScriptHost host)
|
||||
protected void setupUserHost(ScriptHost host)
|
||||
{
|
||||
super.transferToChild(host);
|
||||
super.setupUserHost(host);
|
||||
// transfer Events
|
||||
CarpetEventServer.Event.transferAllHostEventsToChild((CarpetScriptHost) host);
|
||||
CarpetScriptHost child = (CarpetScriptHost) host;
|
||||
CarpetEventServer.Event.transferAllHostEventsToChild(child);
|
||||
FunctionValue onStart = child.getFunction("__on_start");
|
||||
if (onStart != null) child.callNow(onStart, Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -261,7 +264,9 @@ public class CarpetScriptHost extends ScriptHost
|
||||
{
|
||||
try
|
||||
{
|
||||
Value ret = callUDF(BlockPos.ORIGIN, scriptServer.server.getCommandSource(), getFunction("__config"), Collections.emptyList());
|
||||
FunctionValue configFunction = getFunction("__config");
|
||||
if (configFunction == null) return false;
|
||||
Value ret = callNow(configFunction, Collections.emptyList());
|
||||
if (!(ret instanceof MapValue)) return false;
|
||||
Map<Value, Value> config = ((MapValue) ret).getMap();
|
||||
setPerPlayer(config.getOrDefault(new StringValue("scope"), new StringValue("player")).getString().equalsIgnoreCase("player"));
|
||||
@@ -283,7 +288,7 @@ public class CarpetScriptHost extends ScriptHost
|
||||
}
|
||||
appConfig = config;
|
||||
}
|
||||
catch (NullPointerException | InvalidCallbackException ignored)
|
||||
catch (NullPointerException ignored)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -631,23 +636,31 @@ public class CarpetScriptHost extends ScriptHost
|
||||
return Value.NULL;
|
||||
}
|
||||
|
||||
public Value callNow(FunctionValue fun, List<Value> arguments)
|
||||
{
|
||||
ServerPlayerEntity player = (user==null)?null:scriptServer.server.getPlayerManager().getPlayer(user);
|
||||
ServerCommandSource source = (player != null)?player.getCommandSource():scriptServer.server.getCommandSource();
|
||||
try
|
||||
{
|
||||
return callUDF(BlockPos.ORIGIN, source, fun, arguments);
|
||||
}
|
||||
catch (InvalidCallbackException ignored)
|
||||
{
|
||||
return Value.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClose()
|
||||
{
|
||||
super.onClose();
|
||||
FunctionValue closing = getFunction("__on_close");
|
||||
if (closing != null)
|
||||
if (closing != null && (parent != null || !isPerUser()))
|
||||
// either global instance of a global task, or
|
||||
// user host in player scoped app
|
||||
{
|
||||
ServerPlayerEntity player = (user==null)?null:scriptServer.server.getPlayerManager().getPlayer(user);
|
||||
ServerCommandSource source = (player != null)?player.getCommandSource():scriptServer.server.getCommandSource();
|
||||
try
|
||||
{
|
||||
callUDF(BlockPos.ORIGIN, source, closing, Collections.emptyList());
|
||||
}
|
||||
catch (InvalidCallbackException ignored)
|
||||
{
|
||||
}
|
||||
callNow(closing, Collections.emptyList());
|
||||
}
|
||||
if (user == null)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -300,6 +301,12 @@ public class CarpetScriptServer
|
||||
// that will provide player hosts right at the startup
|
||||
newHost.retrieveForExecution(source, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// global app - calling start now.
|
||||
FunctionValue onStart = newHost.getFunction("__on_start");
|
||||
if (onStart != null) newHost.callNow(onStart, Collections.emptyList());
|
||||
}
|
||||
long end = System.nanoTime();
|
||||
CarpetSettings.LOG.info("App "+name+" loaded in "+(end-start)/1000000+" ms");
|
||||
return true;
|
||||
|
||||
@@ -322,12 +322,12 @@ public abstract class ScriptHost
|
||||
if (oldUserHost != null) return oldUserHost;
|
||||
ScriptHost userHost = this.duplicate();
|
||||
userHost.user = user;
|
||||
this.transferToChild(userHost);
|
||||
this.setupUserHost(userHost);
|
||||
userHosts.put(user, userHost);
|
||||
return userHost;
|
||||
}
|
||||
|
||||
protected void transferToChild(ScriptHost host)
|
||||
protected void setupUserHost(ScriptHost host)
|
||||
{
|
||||
// adding imports
|
||||
host.modules.putAll(this.modules);
|
||||
|
||||
@@ -312,3 +312,19 @@ __on_player_swings_hand(player, hand) ->
|
||||
print(' - player: '+player);
|
||||
print(' - hand: '+hand);
|
||||
);
|
||||
|
||||
__on_start() ->
|
||||
(
|
||||
print('');
|
||||
print('__on_start(player)');
|
||||
print('App is starting for '+player());
|
||||
logger('starting for '+player());
|
||||
);
|
||||
|
||||
__on_close() ->
|
||||
(
|
||||
print('');
|
||||
print('__on_close(player)');
|
||||
print('App is closing for '+player());
|
||||
logger('App is closing for '+player());
|
||||
);
|
||||
Reference in new issue
Block a user