From 07de4fb4a58bf8c676f97ff6bb35d0fde85ad22a Mon Sep 17 00:00:00 2001
From: gnembon <41132274+gnembon@users.noreply.github.com>
Date: Fri, 14 Feb 2025 13:17:49 +0100
Subject: [PATCH] commands output reliable return values and new result for
`run` if not run directly
---
docs/scarpet/api/Auxiliary.md | 18 ++++++++++++++----
.../carpet/network/ServerNetworkHandler.java | 4 +++-
src/main/java/carpet/script/api/Auxiliary.java | 10 ++++++++--
.../script/utils/SnoopyCommandSource.java | 12 ++++++------
4 files changed, 31 insertions(+), 13 deletions(-)
diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md
index 8427523e..5a3915fb 100644
--- a/docs/scarpet/api/Auxiliary.md
+++ b/docs/scarpet/api/Auxiliary.md
@@ -410,11 +410,21 @@ Runs a vanilla command from the string result of the `expr` and returns a triple
intercepted list of output messages, and error message if the command resulted in a failure.
Successful commands return `null` as their error.
+The command return `null` if the command was not run immediately, but was scheduled for later execution
+due to being requested while command was executed. This happens most commonly
+when running `run` from a `/script run/invoke` command since that always results in piling up command to run while `script` is being executed.
+
+The mitigation for this is to use `run` in a separate scheduled function, or use `run` in a `tick` event, or literally in
+any other way than directly from a `/script` command, which will ensure that the command runs immediately.
+
-run('fill 1 1 1 10 10 10 air') -> [0, ["Successfully filled 123 blocks"], null]
-run('give @s stone 4') -> [0, ["Gave 4 [Stone] to gnembon"], null]
-run('seed') -> [0, ["Seed: [4031384495743822299]"], null]
-run('sed') -> [0, [], "sed<--[HERE]"] // wrong command
+run('fill 1 1 1 10 10 10 air') -> [123, ["Successfully filled 123 blocks"], null]
+run('give @s stone 4') -> [1, ["Gave 4 [Stone] to gnembon"], null]
+run('seed') -> [-170661413, [Seed: [4031384495743822299]], null]
+run('sed') -> [-1, [], "sed<--[HERE]"] // wrong command
+
+/script run run('setblock 0 0 0 stone') -> null
+/script run schedule(0, _() -> print(run('setblock 0 0 0 stone'))) -> [1, [Changed the block at 0, 0, 0], null]
### `save()`
diff --git a/src/main/java/carpet/network/ServerNetworkHandler.java b/src/main/java/carpet/network/ServerNetworkHandler.java
index 771bbaaa..2770e005 100644
--- a/src/main/java/carpet/network/ServerNetworkHandler.java
+++ b/src/main/java/carpet/network/ServerNetworkHandler.java
@@ -83,6 +83,7 @@ public class ServerNetworkHandler
String id = commandData.getString("id");
List output = new ArrayList<>();
Component[] error = {null};
+ int[] returnValue = {0};
if (player.getServer() == null)
{
error[0] = Component.literal("No Server");
@@ -90,7 +91,7 @@ public class ServerNetworkHandler
else
{
player.getServer().getCommands().performPrefixedCommand(
- new SnoopyCommandSource(player, error, output), command
+ new SnoopyCommandSource(player, error, output, returnValue), command
);
}
CompoundTag result = new CompoundTag();
@@ -99,6 +100,7 @@ public class ServerNetworkHandler
{
result.putString("error", error[0].getContents().toString());
}
+ result.putInt("return", returnValue[0]);
ListTag outputResult = new ListTag();
for (Component line : output)
{
diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java
index 960d44b7..4770a03f 100644
--- a/src/main/java/carpet/script/api/Auxiliary.java
+++ b/src/main/java/carpet/script/api/Auxiliary.java
@@ -97,6 +97,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.OptionalLong;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
@@ -684,12 +685,17 @@ public class Auxiliary
try
{
Component[] error = {null};
+ OptionalLong[] returnValue = {OptionalLong.empty()};
List output = new ArrayList<>();
s.getServer().getCommands().performPrefixedCommand(
- new SnoopyCommandSource(s, error, output),
+ new SnoopyCommandSource(s, error, output, returnValue),
lv.get(0).getString());
+ if (returnValue[0].isEmpty())
+ {
+ return Value.NULL;
+ }
return ListValue.of(
- NumericValue.ZERO,
+ NumericValue.of(returnValue[0].getAsLong()),
ListValue.wrap(output.stream().map(FormattedTextValue::new)),
FormattedTextValue.of(error[0])
);
diff --git a/src/main/java/carpet/script/utils/SnoopyCommandSource.java b/src/main/java/carpet/script/utils/SnoopyCommandSource.java
index fc2315db..74955665 100644
--- a/src/main/java/carpet/script/utils/SnoopyCommandSource.java
+++ b/src/main/java/carpet/script/utils/SnoopyCommandSource.java
@@ -19,6 +19,7 @@ import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import java.util.List;
+import java.util.OptionalLong;
import java.util.function.BinaryOperator;
import java.util.function.Supplier;
@@ -43,11 +44,11 @@ public class SnoopyCommandSource extends CommandSourceStack
private final TaskChainer taskChainer;
- public SnoopyCommandSource(CommandSourceStack original, Component[] error, List chatOutput)
+ public SnoopyCommandSource(CommandSourceStack original, Component[] error, List chatOutput, OptionalLong[] returnValue)
{
super(CommandSource.NULL, original.getPosition(), original.getRotation(), original.getLevel(), Vanilla.MinecraftServer_getRunPermissionLevel(original.getServer()),
original.getTextName(), original.getDisplayName(), original.getServer(), original.getEntity(), false,
- CommandResultCallback.EMPTY, EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(original.getServer()));
+ (b, i) -> returnValue[0] = OptionalLong.of(i), EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(original.getServer()));
this.output = CommandSource.NULL;
this.position = original.getPosition();
this.world = original.getLevel();
@@ -56,7 +57,7 @@ public class SnoopyCommandSource extends CommandSourceStack
this.name = original.getDisplayName();
this.server = original.getServer();
this.entity = original.getEntity();
- this.resultConsumer = CommandResultCallback.EMPTY;
+ this.resultConsumer = (b, i) -> returnValue[0] = OptionalLong.of(i);
this.entityAnchor = original.getAnchor();
this.rotation = original.getRotation();
this.error = error;
@@ -65,7 +66,7 @@ public class SnoopyCommandSource extends CommandSourceStack
this.taskChainer = TaskChainer.immediate(original.getServer());
}
- public SnoopyCommandSource(ServerPlayer player, Component[] error, List output)
+ public SnoopyCommandSource(ServerPlayer player, Component[] error, List output, int [] result)
{
super(player.commandSource(), player.position(), player.getRotationVector(),
player.level() instanceof final ServerLevel serverLevel ? serverLevel : null,
@@ -79,7 +80,7 @@ public class SnoopyCommandSource extends CommandSourceStack
this.name = player.getDisplayName();
this.server = player.level().getServer();
this.entity = player;
- this.resultConsumer = CommandResultCallback.EMPTY;
+ this.resultConsumer = (b, i) -> result[0] = i;
this.entityAnchor = EntityAnchorArgument.Anchor.FEET;
this.rotation = player.getRotationVector(); // not a client call really
this.error = error;
@@ -203,5 +204,4 @@ public class SnoopyCommandSource extends CommandSourceStack
{
chatOutput.add(message.get());
}
-
}