diff --git a/src/main/java/carpet/network/ServerNetworkHandler.java b/src/main/java/carpet/network/ServerNetworkHandler.java index a3f23622..b647306f 100644 --- a/src/main/java/carpet/network/ServerNetworkHandler.java +++ b/src/main/java/carpet/network/ServerNetworkHandler.java @@ -3,6 +3,7 @@ package carpet.network; import carpet.CarpetServer; import carpet.CarpetSettings; import carpet.helpers.TickSpeed; +import carpet.script.utils.SnoopyCommandSource; import carpet.settings.ParsedRule; import carpet.settings.SettingsManager; import io.netty.buffer.Unpooled; @@ -12,10 +13,9 @@ import net.minecraft.nbt.NbtString; import net.minecraft.nbt.NbtElement; import net.minecraft.network.PacketByteBuf; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; -import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import java.util.ArrayList; @@ -93,38 +93,22 @@ public class ServerNetworkHandler String command = commandData.getString("command"); String id = commandData.getString("id"); List output = new ArrayList<>(); - String[] error = {null}; + Text[] error = {null}; int resultCode = -1; if (player.getServer() == null) { - error[0] = "No Server"; + error[0] = new LiteralText("No Server"); } else { resultCode = player.getServer().getCommandManager().execute( - new ServerCommandSource(player, player.getPos(), player.getRotationClient(), - player.world instanceof ServerWorld ? (ServerWorld) player.world : null, - player.server.getPermissionLevel(player.getGameProfile()), player.getName().getString(), player.getDisplayName(), - player.world.getServer(), player) - { - @Override - public void sendError(Text message) - { - error[0] = message.getString(); - } - @Override - public void sendFeedback(Text message, boolean broadcastToOps) - { - output.add(message); - } - }, - command + new SnoopyCommandSource(player, error, output), command ); - }; - NbtCompound result = new NbtCompound(); + } + CompoundTag result = new CompoundTag(); result.putString("id", id); result.putInt("code", resultCode); - if (error[0] != null) result.putString("error", error[0]); + if (error[0] != null) result.putString("error", error[0].asString()); NbtList outputResult = new NbtList(); for (Text line: output) outputResult.add(NbtString.of(Text.Serializer.toJson(line))); if (!output.isEmpty()) result.put("output", outputResult); diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index 20d68eba..747419dc 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -669,13 +669,17 @@ public class Auxiliary { ServerCommandSource s = ((CarpetContext)c).s; try { - Value[] error = {Value.NULL}; - List output = new ArrayList<>(); + Text[] error = {null}; + List output = new ArrayList<>(); Value retval = new NumericValue(s.getMinecraftServer().getCommandManager().execute( new SnoopyCommandSource(s, posf, error, output), lv.get(0).evalValue(c).getString()) ); - Value ret = ListValue.of(retval, ListValue.wrap(output), error[0]); + Value ret = ListValue.of( + retval, + ListValue.wrap(output.stream().map(FormattedTextValue::new).collect(Collectors.toList())), + FormattedTextValue.of(error[0]) + ); return (c_, t_) -> ret; } catch (Exception exc) diff --git a/src/main/java/carpet/script/utils/SnoopyCommandSource.java b/src/main/java/carpet/script/utils/SnoopyCommandSource.java index 99c74a47..5747d8a2 100644 --- a/src/main/java/carpet/script/utils/SnoopyCommandSource.java +++ b/src/main/java/carpet/script/utils/SnoopyCommandSource.java @@ -1,10 +1,7 @@ package carpet.script.utils; import carpet.CarpetSettings; -import carpet.script.value.FormattedTextValue; -import carpet.script.value.Value; import com.mojang.brigadier.ResultConsumer; -import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.command.argument.EntityAnchorArgumentType; import net.minecraft.entity.Entity; @@ -14,41 +11,90 @@ import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec2f; import net.minecraft.util.math.Vec3d; import net.minecraft.world.dimension.DimensionType; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.function.BinaryOperator; public class SnoopyCommandSource extends ServerCommandSource { - private Vec3d position; - private ServerWorld world; - private String simpleName; - private Text name; + private final CommandOutput output; + private final Vec3d position; + private final ServerWorld world; + private final int level; + private final String simpleName; + private final Text name; private final MinecraftServer server; - private Entity entity; - private ResultConsumer resultConsumer; - private EntityAnchorArgumentType.EntityAnchor entityAnchor; - private Vec2f rotation; - private final Value[] error; - private final List chatOutput; + // skipping silent since snooper is never silent + private final Entity entity; + private final ResultConsumer resultConsumer; + private final EntityAnchorArgumentType.EntityAnchor entityAnchor; + private final Vec2f rotation; + // good stuff + private final Text[] error; + private final List chatOutput; - public SnoopyCommandSource(ServerCommandSource original, Vec3d pos, Value[] error, List chatOutput) + public SnoopyCommandSource(ServerCommandSource original, Vec3d pos, Text[] error, List chatOutput) { super(CommandOutput.DUMMY, pos, Vec2f.ZERO, original.getWorld(), CarpetSettings.runPermissionLevel, original.getName(), original.getDisplayName(), original.getMinecraftServer(), original.getEntity(), false, (ctx, succ, res) -> { }, EntityAnchorArgumentType.EntityAnchor.FEET); - position = pos; - world = original.getWorld(); - simpleName = original.getName(); - name = original.getDisplayName(); - server = original.getMinecraftServer(); - entity = original.getEntity(); - resultConsumer = (ctx, succ, res) -> { }; - entityAnchor = original.getEntityAnchor(); - rotation = Vec2f.ZERO; + this.output = CommandOutput.DUMMY; + this.position = pos; + this.world = original.getWorld(); + this.level = CarpetSettings.runPermissionLevel; + this.simpleName = original.getName(); + this.name = original.getDisplayName(); + this.server = original.getMinecraftServer(); + this.entity = original.getEntity(); + this.resultConsumer = (ctx, succ, res) -> { }; + this.entityAnchor = original.getEntityAnchor(); + this.rotation = Vec2f.ZERO; + this.error = error; + this.chatOutput = chatOutput; + } + + public SnoopyCommandSource(ServerPlayerEntity player, Text[] error, List output) { + super(player, player.getPos(), player.getRotationClient(), + player.world instanceof ServerWorld ? (ServerWorld) player.world : null, + player.server.getPermissionLevel(player.getGameProfile()), player.getName().getString(), player.getDisplayName(), + player.world.getServer(), player); + this.output = player; + this.position = player.getPos(); + this.world = player.world instanceof ServerWorld ? (ServerWorld) player.world : null; + this.level = player.server.getPermissionLevel(player.getGameProfile()); + this.simpleName = player.getName().getString(); + this.name = player.getDisplayName(); + this.server = player.world.getServer(); + this.entity = player; + this.resultConsumer = (ctx, succ, res) -> { }; + this.entityAnchor = EntityAnchorArgumentType.EntityAnchor.FEET; + this.rotation = Vec2f.ZERO; + this.error = error; + this.chatOutput = output; + } + + private SnoopyCommandSource(CommandOutput output, Vec3d pos, Vec2f rot, ServerWorld world, int level, String simpleName, Text name, MinecraftServer server, @Nullable Entity entity, ResultConsumer consumer, EntityAnchorArgumentType.EntityAnchor entityAnchor, + Text[] error, List chatOutput + ) { + super(output, pos, rot, world, level, + simpleName, name, server, entity, false, + consumer, entityAnchor); + this.output = output; + this.position = pos; + this.rotation = rot; + this.world = world; + this.level = level; + this.simpleName = simpleName; + this.name = name; + this.server = server; + this.entity = entity; + this.resultConsumer = consumer; + this.entityAnchor = entityAnchor; this.error = error; this.chatOutput = chatOutput; } @@ -56,31 +102,30 @@ public class SnoopyCommandSource extends ServerCommandSource @Override public ServerCommandSource withEntity(Entity entity) { - this.entity = entity; - this.simpleName = entity.getName().getString(); - this.name = entity.getDisplayName(); - return this; + return new SnoopyCommandSource(output, position, rotation, world, level, entity.getName().getString(), entity.getDisplayName(), server, entity, resultConsumer, entityAnchor, error, chatOutput); } @Override public ServerCommandSource withPosition(Vec3d position) { - this.position = position; - return this; + return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, entityAnchor, error, chatOutput); } @Override public ServerCommandSource withRotation(Vec2f rotation) { - this.rotation = rotation; - return this; + return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, entityAnchor, error, chatOutput); } @Override public ServerCommandSource withConsumer(ResultConsumer consumer) { - this.resultConsumer = consumer; - return this; + return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, consumer, entityAnchor, error, chatOutput); + } + + public ServerCommandSource mergeConsumers(ResultConsumer consumer, BinaryOperator> binaryOperator) { + ResultConsumer resultConsumer = binaryOperator.apply(this.resultConsumer, consumer); + return this.withConsumer(resultConsumer); } //@Override // only used in fuctions and we really don't care to track these actually, besides the basic output @@ -102,103 +147,37 @@ public class SnoopyCommandSource extends ServerCommandSource @Override public ServerCommandSource withEntityAnchor(EntityAnchorArgumentType.EntityAnchor anchor) { - entityAnchor = anchor; - return this; + return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, anchor, error, chatOutput); } @Override public ServerCommandSource withWorld(ServerWorld world) { - this.world = world; double d = DimensionType.getCoordinateScaleFactor(this.world.getDimension(), world.getDimension()); - this.position = new Vec3d(this.position.x * d, this.position.y, this.position.z * d); - return this; + Vec3d position = new Vec3d(this.position.x * d, this.position.y, this.position.z * d); + return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, entityAnchor, error, chatOutput); } - @Override - public Text getDisplayName() - { - return name; - } - - @Override - public String getName() - { - return simpleName; - } - - @Override - public Vec3d getPosition() - { - return position; - } - - @Override - public ServerWorld getWorld() - { - return world; - } - - @Override - public Entity getEntity() - { - return entity; - } - - @Override - public Entity getEntityOrThrow() throws CommandSyntaxException - { - if (entity == null) { - throw REQUIRES_ENTITY_EXCEPTION.create(); - } else { - return entity; - } - } - - @Override - public ServerPlayerEntity getPlayer() throws CommandSyntaxException - { - if (!(this.entity instanceof ServerPlayerEntity)) { - throw REQUIRES_PLAYER_EXCEPTION.create(); - } else { - return (ServerPlayerEntity)this.entity; - } - } - - @Override - public Vec2f getRotation() - { - return rotation; - } - - @Override - public MinecraftServer getMinecraftServer() - { - return server; - } - - @Override - public EntityAnchorArgumentType.EntityAnchor getEntityAnchor() - { - return entityAnchor; - } - - - @Override - public void onCommandComplete(CommandContext context, boolean success, int result) - { - if (this.resultConsumer != null) resultConsumer.onCommandComplete(context, success, result); + public ServerCommandSource withLookingAt(Vec3d position) throws CommandSyntaxException { + Vec3d vec3d = this.entityAnchor.positionAt(this); + double d = position.x - vec3d.x; + double e = position.y - vec3d.y; + double f = position.z - vec3d.z; + double g = (double) MathHelper.sqrt(d * d + f * f); + float h = MathHelper.wrapDegrees((float)(-(MathHelper.atan2(e, g) * 57.2957763671875D))); + float i = MathHelper.wrapDegrees((float)(MathHelper.atan2(f, d) * 57.2957763671875D) - 90.0F); + return this.withRotation(new Vec2f(h, i)); } @Override public void sendError(Text message) { - error[0] = new FormattedTextValue(message); + error[0] = message; } @Override public void sendFeedback(Text message, boolean broadcastToOps) { - chatOutput.add(new FormattedTextValue(message)); + chatOutput.add(message); } } diff --git a/src/main/java/carpet/script/value/FormattedTextValue.java b/src/main/java/carpet/script/value/FormattedTextValue.java index f7eb80a0..9f68c786 100644 --- a/src/main/java/carpet/script/value/FormattedTextValue.java +++ b/src/main/java/carpet/script/value/FormattedTextValue.java @@ -42,6 +42,11 @@ public class FormattedTextValue extends StringValue } } + public static Value of(Text text) { + if (text == null) return Value.NULL; + return new FormattedTextValue(text); + } + @Override public String getString() { return text.getString();