Merge branch 'master' into 1.17

This commit is contained in:
gnembon committed 2021-02-08 23:54:23 -04:00
commit 6108cdce23
17 files changed
+174 -66

No files matched your search

+2 -1
View File
@@ -159,7 +159,8 @@ jobs:
"id": "carpet",
"version": "1.4.11",
"entrypoints": {
"preLaunch": [ "carpet.utils.RulePrinter" ]
"server": [ "carpet.utils.CarpetRulePrinter" ],
"preLaunch": [ "carpet.utils.CarpetRulePrinter" ]
}
}' > fabric.mod.json
cd ../../../
+1 -1
View File
@@ -4183,7 +4183,7 @@ ingested by the player. The exact position of these items is unknown as technica
items could be spread all across the inventory.
### `__on_player_connects(player)`
Triggered when the player has successfully logged in and was placed in the gaem.
Triggered when the player has successfully logged in and was placed in the game.
### `__on_player_disconnects(player, reason)`
Triggered when a player sends a disconnect package or is forcefully disconnected from the server.
+21
View File
@@ -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`.
+5
View File
@@ -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
+5 -4
View File
@@ -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
+15 -14
View File
@@ -171,14 +171,22 @@ public class CarpetServer implements ClientModInitializer,DedicatedServerModInit
public static void onServerClosed(MinecraftServer server)
{
if (scriptServer != null) scriptServer.onClose();
ServerNetworkHandler.close();
currentCommandDispatcher = null;
// this for whatever reason gets called multiple times even when joining on SP
// so we allow to pass multiple times gating it only on existing server ref
if (minecraft_server != null)
{
if (scriptServer != null) scriptServer.onClose();
ServerNetworkHandler.close();
currentCommandDispatcher = null;
LoggerRegistry.stopLoggers();
extensions.forEach(e -> e.onServerClosed(server));
minecraft_server = null;
disconnect();
LoggerRegistry.stopLoggers();
extensions.forEach(e -> e.onServerClosed(server));
minecraft_server = null;
}
// this for whatever reason gets called multiple times even when joining;
TickSpeed.reset();
settingsManager.detachServer();
}
public static void registerExtensionLoggers()
@@ -186,13 +194,6 @@ public class CarpetServer implements ClientModInitializer,DedicatedServerModInit
extensions.forEach(CarpetExtension::registerLoggers);
}
public static void disconnect()
{
// this for whatever reason gets called multiple times even when joining;
TickSpeed.reset();
settingsManager.detachServer();
}
public static void onReload(MinecraftServer server)
{
scriptServer.reload(server);
@@ -5,6 +5,7 @@ import carpet.script.utils.ShapesRenderer;
import carpet.utils.FabricAPIHooks;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gl.ShaderEffect;
import net.minecraft.client.render.BufferBuilderStorage;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.GameRenderer;
@@ -13,6 +14,7 @@ import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.Matrix4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -20,16 +22,39 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(WorldRenderer.class)
public class WorldRenderer_scarpetRenderMixin
{
@Shadow private /*@Nullable*/ ShaderEffect transparencyShader;
@Inject(method = "<init>", at = @At("RETURN"))
private void addRenderers(MinecraftClient client, BufferBuilderStorage bufferBuilders, CallbackInfo ci)
{
CarpetClient.shapes = new ShapesRenderer(client);
}
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/debug/DebugRenderer;render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider$Immediate;DDD)V"))
@Inject(method = "render", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/render/WorldRenderer;renderChunkDebugInfo(Lnet/minecraft/client/render/Camera;)V",
shift = At.Shift.AFTER
))
private void renderScarpetThings(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci)
{
if (!FabricAPIHooks.WORLD_RENDER_EVENTS && CarpetClient.shapes != null)
// in normal circumstances we want to render shapes at the very end so it appears correctly behind stuff.
if (!FabricAPIHooks.WORLD_RENDER_EVENTS && CarpetClient.shapes != null && transparencyShader == null)
{
RenderSystem.pushMatrix();
CarpetClient.shapes.render(camera, tickDelta);
RenderSystem.popMatrix();
}
}
@Inject(method = "render", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/render/debug/DebugRenderer;render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider$Immediate;DDD)V",
shift = At.Shift.AFTER
))
private void renderScarpetThingsFabulously(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci)
{
// with fabulous graphics - stuff doesn't work this way for some reason - need to render with chunk lines.
if (!FabricAPIHooks.WORLD_RENDER_EVENTS && CarpetClient.shapes != null && transparencyShader != null)
{
RenderSystem.pushMatrix();
CarpetClient.shapes.render(camera, tickDelta);
@@ -39,7 +39,7 @@ public class CarpetClient
{
isServerCarpet = false;
clientPlayer = null;
CarpetServer.disconnect();
CarpetServer.onServerClosed(null);
}
public static void setCarpet()
@@ -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;
+1 -1
View File
@@ -149,7 +149,7 @@ public abstract class Fluff
{
try
{
return (c, type_ignored) -> AbstractOperator.this.eval(v1.evalValue(c, type), v2.evalValue(c, type));
return (c, type_ignored) -> AbstractOperator.this.eval(v1.evalValue(c, Context.NONE), v2.evalValue(c, Context.NONE));
}
catch (RuntimeException exc)
{
+2 -2
View File
@@ -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);
@@ -100,6 +100,7 @@ public class Loops {
expression.addLazyFunction("map", 2, (c, t, lv) ->
{
Value rval= lv.get(0).evalValue(c, Context.NONE);
if (rval.isNull()) return ListValue.lazyEmpty();
if (!(rval instanceof AbstractListValue))
throw new InternalExpressionException("First argument of 'map' function should be a list or iterator");
Iterator<Value> iterator = ((AbstractListValue) rval).iterator();
@@ -145,6 +146,7 @@ public class Loops {
expression.addLazyFunction("filter", 2, (c, t, lv) ->
{
Value rval= lv.get(0).evalValue(c, Context.NONE);
if (rval.isNull()) return ListValue.lazyEmpty();
if (!(rval instanceof AbstractListValue))
throw new InternalExpressionException("First argument of 'filter' function should be a list or iterator");
Iterator<Value> iterator = ((AbstractListValue) rval).iterator();
@@ -192,6 +194,7 @@ public class Loops {
{
Value rval= lv.get(0).evalValue(c, Context.NONE);
if (rval.isNull()) return LazyValue.NULL;
if (!(rval instanceof AbstractListValue))
throw new InternalExpressionException("First argument of 'first' function should be a list or iterator");
Iterator<Value> iterator = ((AbstractListValue) rval).iterator();
@@ -243,6 +246,7 @@ public class Loops {
expression.addLazyFunction("all", 2, (c, t, lv) ->
{
Value rval= lv.get(0).evalValue(c, Context.NONE);
if (rval.isNull()) return LazyValue.TRUE;
if (!(rval instanceof AbstractListValue))
throw new InternalExpressionException("First argument of 'all' function should be a list or iterator");
Iterator<Value> iterator = ((AbstractListValue) rval).iterator();
@@ -307,6 +311,7 @@ public class Loops {
expression.addLazyFunction("for", 2, (c, t, lv) ->
{
Value rval= lv.get(0).evalValue(c, Context.NONE);
if (rval.isNull()) return LazyValue.ZERO;
if (!(rval instanceof AbstractListValue))
throw new InternalExpressionException("First argument of 'for' function should be a list or iterator");
Iterator<Value> iterator = ((AbstractListValue) rval).iterator();
@@ -356,12 +361,13 @@ public class Loops {
// returned value is substituted to the accumulator
expression.addLazyFunction("reduce", 3, (c, t, lv) ->
{
LazyValue expr = lv.get(1);
Value acc = lv.get(2).evalValue(c, Context.NONE);
Value rval= lv.get(0).evalValue(c, Context.NONE);
if (rval.isNull()) return ListValue.lazyEmpty();
if (!(rval instanceof AbstractListValue))
throw new InternalExpressionException("First argument of 'reduce' should be a list or iterator");
LazyValue expr = lv.get(1);
Value acc = lv.get(2).evalValue(c, Context.NONE);
Iterator<Value> iterator = ((AbstractListValue) rval).iterator();
if (!iterator.hasNext())
@@ -0,0 +1,33 @@
package carpet.utils;
import carpet.CarpetServer;
import net.fabricmc.api.DedicatedServerModInitializer;
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
import java.io.PrintStream;
import java.lang.System;
/**
* Runs only from GitHub Actions to generate the wiki
* page with all Carpet rules on it.
* It is here so it can be managed by the IDE
*
*/
public class CarpetRulePrinter implements DedicatedServerModInitializer, PreLaunchEntrypoint {
public static final PrintStream OLD_OUT = System.out;
@Override
public void onInitializeServer() {
// Minecraft (or whatever) changes the System.out to have prefixes,
// our simple parser doesn't like that. So we change it back
System.setOut(OLD_OUT);
CarpetServer.onGameStarted();
CarpetServer.settingsManager.printAllRulesToLog(null);
System.exit(0);
}
@Override
public void onPreLaunch() {
// Just initializes our OLD_OUT by nooping the class
}
}
@@ -1,22 +0,0 @@
package carpet.utils;
import carpet.CarpetServer;
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
import java.lang.System;
/**
* Runs only from GitHub Actions to generate the wiki
* page with all Carpet rules on it.
* It is here so it can be managed by the IDE
*
* @author altrisi
*
*/
public class RulePrinter implements PreLaunchEntrypoint {
@Override
public void onPreLaunch() {
CarpetServer.onGameStarted();
CarpetServer.settingsManager.printAllRulesToLog(null);
System.exit(0);
}
}
@@ -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());
);