From 2f514838b62f106253c99d123f67cddfff7e9f45 Mon Sep 17 00:00:00 2001 From: AV3_08 <66512356+AV306@users.noreply.github.com> Date: Thu, 23 May 2024 08:10:30 +0000 Subject: [PATCH] compliance --- build.gradle | 2 +- gradle.properties | 2 +- init | 2 +- .../java/me/av306/xenon/MainInitializer.java | 14 ++-- src/main/java/me/av306/xenon/Xenon.java | 77 +++++++++---------- .../me/av306/xenon/event/GetFovEvent.java | 20 +++++ .../java/me/av306/xenon/feature/IFeature.java | 6 +- .../xenon/feature/IToggleableFeature.java | 9 ++- .../render/ProximityRadarFeature.java | 2 + .../me/av306/xenon/mixin/BowItemMixin.java | 40 ---------- .../me/av306/xenon/mixin/ChatScreenMixin.java | 4 - .../xenon/mixin/EntityRendererMixin.java | 7 +- .../av306/xenon/mixin/GameRendererMixin.java | 52 +++++++------ .../av306/xenon/mixin/RenderSystemMixin.java | 9 +-- .../xenon/packets/OptInPacketPayload.java | 18 +++++ .../xenon/packets/OptOutPacketPayload.java | 18 +++++ .../resources/assets/xenon/lang/en_us.json | 2 +- 17 files changed, 155 insertions(+), 129 deletions(-) delete mode 100644 src/main/java/me/av306/xenon/mixin/BowItemMixin.java create mode 100644 src/main/java/me/av306/xenon/packets/OptInPacketPayload.java create mode 100644 src/main/java/me/av306/xenon/packets/OptOutPacketPayload.java diff --git a/build.gradle b/build.gradle index ac58a8f6..cfcafbe9 100644 --- a/build.gradle +++ b/build.gradle @@ -71,7 +71,7 @@ processResources { tasks.withType( JavaCompile ).configureEach { // Minecraft 1.18 (1.18-pre2) upwards uses Java 17. - it.options.release = 17 + it.options.release = 21 //it.options.compilerArgs.add( "--enable-preview" ) } diff --git a/gradle.properties b/gradle.properties index 07114132..9dd47fb3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,7 +16,7 @@ archives_base_name = xenon # Complete Config - complete_config_version = 2.5.3 + complete_config_version = 2.5.4 # SLF4J slf4j_version = 2.0.7 diff --git a/init b/init index 5e61012a..3cdb6d7a 100755 --- a/init +++ b/init @@ -16,7 +16,7 @@ sudo apt update sudo apt install qt6-base-dev libqt6core5compat6 -y -sudo apt install tcpdump -y +#sudo apt install tcpdump -y # Cleanup sudo apt autoremove diff --git a/src/main/java/me/av306/xenon/MainInitializer.java b/src/main/java/me/av306/xenon/MainInitializer.java index aa6bd2e7..bd0d8f0d 100644 --- a/src/main/java/me/av306/xenon/MainInitializer.java +++ b/src/main/java/me/av306/xenon/MainInitializer.java @@ -1,5 +1,6 @@ package me.av306.xenon; +import me.av306.xenon.packets.OptInPacketPayload; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; @@ -12,16 +13,17 @@ public class MainInitializer implements ModInitializer @Override public void onInitialize() { - Xenon.INSTANCE.LOGGER.info( "Doing server-side initialisation..." ); + //if ( ) + Xenon.INSTANCE.LOGGER.info( "Doing logical server-side initialisation..." ); // TODO ServerPlayConnectionEvents.JOIN.register( (handler, sender, server) -> { - /*Packet packet = new P - PacketByteBuf pak = PacketByteBufs.create(); - pak.writeString( "timer" ); - sender.sendPacket( pak ); - //sender.sendPacket( Xenon.INSTANCE.BLOCKED_FEATURE_PACKET, pak );*/ + // Uncomment this line and replace the placeholder text + // with the name of the feature you wish to block. + // Timer and ProxRadar are blocked by default, and will be + // removed in a future version. + //sender.sendPacket( new OptOutPacketPayload( "[FEATURE_NAME_HERE]" ) ); } ); } } diff --git a/src/main/java/me/av306/xenon/Xenon.java b/src/main/java/me/av306/xenon/Xenon.java index 9ed1167d..268342ea 100644 --- a/src/main/java/me/av306/xenon/Xenon.java +++ b/src/main/java/me/av306/xenon/Xenon.java @@ -13,10 +13,13 @@ import me.av306.xenon.features.movement.*; import me.av306.xenon.features.render.*; import me.av306.xenon.mixin.MinecraftClientAccessor; +import me.av306.xenon.packets.OptInPacketPayload; +import me.av306.xenon.packets.OptOutPacketPayload; import me.av306.xenon.util.KeybindUtil; import me.av306.xenon.util.text.TextFactory; import me.lortseam.completeconfig.data.Config; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.Version; @@ -26,6 +29,7 @@ import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; +import net.minecraft.util.dynamic.Codecs; import org.lwjgl.glfw.GLFW; import org.slf4j.LoggerFactory; @@ -83,8 +87,8 @@ public enum Xenon /** * Identifier for the opt-out packet */ - public final Identifier BLOCKED_FEATURE_PACKET = new Identifier( this.MODID, "block_feature" ); - public final Identifier PERMIT_FEATURE_PACKET = new Identifier( this.MODID, "permit_feature" ); + public final Identifier BLOCK_FEATURE_PACKET_ID = new Identifier( this.MODID, "block_feature" ); + public final Identifier PERMIT_FEATURE_PACKET_ID = new Identifier( this.MODID, "permit_feature" ); //private boolean updateAvailable = false; //public boolean getUpdateAvailable() { return updateAvailable; } @@ -116,7 +120,7 @@ public void initialise() ClientWorldEvents.DISCONNECT.register( this::disableAllFeatures ); // Register packet handler - //registerPacketHandlers(); + registerPacketHandlers(); // register features initCommands(); @@ -127,46 +131,41 @@ public void initialise() ConfigScreenBuilder.setMain( this.MODID, new ClothConfigScreenBuilder() );*/ } - /*private void registerPacketHandlers() + private void registerPacketHandlers() { - ClientPlayNetworking.registerGlobalReceiver( - this.BLOCKED_FEATURE_PACKET, - (client, handler, buf, responseSender) -> + PayloadTypeRegistry.playS2C().register( OptOutPacketPayload.ID, OptOutPacketPayload.CODEC ); + ClientPlayNetworking.registerGlobalReceiver( OptOutPacketPayload.ID, (payload, context) -> + { + try { - String name = buf.readString(); - IFeature feature = this.featureRegistry.get( name ); - try - { - feature.setForceDisabled( true ); - this.LOGGER.info( "Server blocks feature: {}", feature.getName() ); - this.sendInfoMessage( "text.xenon.featureblocked", feature.getName() ); - } - catch ( NullPointerException npe ) - { - this.LOGGER.info( "Server blocks non-existent feature: {}", name ); - } + this.featureRegistry.get( payload.featureName() ).setForceDisabled( true ); + this.LOGGER.info( "{} blocked by server", payload.featureName() ); + this.sendInfoMessage( "text.xenon.featureblocked", payload.featureName() ); } - ); + catch ( NullPointerException npe ) + { + // Feature not present, error + this.LOGGER.warn( "Server blocks non-existent feature {}", payload.featureName() ); + } + } ); - ClientPlayNetworking.registerGlobalReceiver( - this.PERMIT_FEATURE_PACKET, - (client, handler, buf, responseSender) -> - { - String name = buf.readString(); - IFeature feature = this.featureRegistry.get( name ); - try - { - feature.setForceDisabled( false ); - this.LOGGER.info( "Server permits feature: {}", feature.getName() ); - this.sendInfoMessage( "text.xenon.featurepermitted", feature.getName() ); - } - catch ( NullPointerException npe ) - { - this.LOGGER.info( "Server permits non-existent feature: {}", name ); - } - } - ); - }*/ + PayloadTypeRegistry.playS2C().register( OptInPacketPayload.ID, OptInPacketPayload.CODEC ); + ClientPlayNetworking.registerGlobalReceiver( OptInPacketPayload.ID, (payload, context) -> + { + try + { + this.featureRegistry.get( payload.featureName() ).setForceDisabled( false ); + this.LOGGER.info( "{} blocked by server", payload.featureName() ); + this.sendInfoMessage( "text.xenon.featurepermitted", payload.featureName() ); + } + catch ( NullPointerException npe ) + { + // Feature not present, error + this.LOGGER.warn( "Server permits non-existent feature {}", payload.featureName() ); + } + + } ); + } private void initCommands() { diff --git a/src/main/java/me/av306/xenon/event/GetFovEvent.java b/src/main/java/me/av306/xenon/event/GetFovEvent.java index b9c74107..d77829af 100644 --- a/src/main/java/me/av306/xenon/event/GetFovEvent.java +++ b/src/main/java/me/av306/xenon/event/GetFovEvent.java @@ -22,8 +22,28 @@ public interface GetFovEvent } ); + Event EVENT2 = EventFactory.createArrayBacked( + GetFovEvent2.class, + (listeners) -> (fov) -> + { + for ( GetFovEvent2 listener : listeners ) + { + ActionResult result = listener.interact( fov ); + + if ( result != ActionResult.PASS ) return result; + } + + return ActionResult.PASS; + } + ); + ActionResult interact( Camera camera, float tickDelta, boolean changingFov ); + public interface GetFovEvent2 + { + ActionResult interact( double fov ); + } + public class EventData { public static double FOV_ZOOM_LEVEL = 1f; diff --git a/src/main/java/me/av306/xenon/feature/IFeature.java b/src/main/java/me/av306/xenon/feature/IFeature.java index ebcaf9f9..13b2293b 100644 --- a/src/main/java/me/av306/xenon/feature/IFeature.java +++ b/src/main/java/me/av306/xenon/feature/IFeature.java @@ -212,7 +212,7 @@ protected void keyEvent() if ( this.keyBinding.wasPressed() ) if ( this.forceDisabled ) // Server wishes to opt out of this feature - this.sendErrorMessage( "text.xenon.ifeature.forcedisabled" ); + this.sendErrorMessage( "text.xenon.ifeature.blocked", this.getName() ); else this.enable(); } @@ -234,11 +234,11 @@ public void enable() //this.isEnabled = true; - if ( this.isForceDisabled() ) + /*if ( this.forceDisabled ) { Xenon.INSTANCE.sendInfoMessage( "text.xenon.featureblocked" ); return; - } + }*/ Xenon.INSTANCE.LOGGER.info( this.getName() + " enabled!" ); diff --git a/src/main/java/me/av306/xenon/feature/IToggleableFeature.java b/src/main/java/me/av306/xenon/feature/IToggleableFeature.java index b8f1bc08..fab89891 100644 --- a/src/main/java/me/av306/xenon/feature/IToggleableFeature.java +++ b/src/main/java/me/av306/xenon/feature/IToggleableFeature.java @@ -97,7 +97,12 @@ protected ActionResult onKeyboardKey( long window, int key, int scanCode, int ac protected void keyEvent() { if ( this.keyBinding.wasPressed() && !Xenon.INSTANCE.modifierKey.isPressed() ) - this.toggle(); + { + if ( this.forceDisabled ) + Xenon.INSTANCE.sendErrorMessage( "text.xenon.ifeature.blocked", this.name ); + + else this.toggle(); + } } @Override @@ -107,7 +112,7 @@ public void enable() this.isEnabled = true; - Xenon.INSTANCE.LOGGER.info( this.getName() + " enabled!" ); + Xenon.INSTANCE.LOGGER.info( "{} enabled!", this.getName() ); Xenon.INSTANCE.enabledFeatures.add( this ); diff --git a/src/main/java/me/av306/xenon/features/render/ProximityRadarFeature.java b/src/main/java/me/av306/xenon/features/render/ProximityRadarFeature.java index d38079ae..9cdde154 100644 --- a/src/main/java/me/av306/xenon/features/render/ProximityRadarFeature.java +++ b/src/main/java/me/av306/xenon/features/render/ProximityRadarFeature.java @@ -36,6 +36,8 @@ public ProximityRadarFeature() { super( "ProximityRadar", "proxradar", "pr" ); + this.setForceDisabled( true ); + // Perform entity scanning in the render thread // because they're gonna be rendered somewhere before this anyway, // and we're rendering stuff too diff --git a/src/main/java/me/av306/xenon/mixin/BowItemMixin.java b/src/main/java/me/av306/xenon/mixin/BowItemMixin.java deleted file mode 100644 index 6c45e590..00000000 --- a/src/main/java/me/av306/xenon/mixin/BowItemMixin.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.av306.xenon.mixin; - -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import me.av306.xenon.Xenon; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.BowItem; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Hand; -import net.minecraft.util.TypedActionResult; -import net.minecraft.world.World; - -@Mixin( BowItem.class ) -public class BowItemMixin -{ - @Inject( - at = @At( "HEAD" ), - method = "use(Lnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/Hand;)Lnet/minecraft/util/TypedActionResult;", - cancellable = true - ) - private void onUse( World world, PlayerEntity plater, Hand hand, CallbackInfoReturnable cir ) - { - Xenon.INSTANCE.sendInfoMessage( "Bow use" ); - } - - @Inject( - at = @At( "HEAD" ), - method = "onStoppedUsing(Lnet/minecraft/item/ItemStack;Lnet/minecraft/world/World;Lnet/minecraft/entity/LivingEntity;I)V", - cancellable = true - ) - private void onStoppedUsing( ItemStack stack, World world, LivingEntity entity, int remainingUseTicks, CallbackInfo ci ) - { - Xenon.INSTANCE.sendInfoMessage( "Bow stop use" ); - } -} diff --git a/src/main/java/me/av306/xenon/mixin/ChatScreenMixin.java b/src/main/java/me/av306/xenon/mixin/ChatScreenMixin.java index 8bbf07c8..d8a1e35d 100644 --- a/src/main/java/me/av306/xenon/mixin/ChatScreenMixin.java +++ b/src/main/java/me/av306/xenon/mixin/ChatScreenMixin.java @@ -12,7 +12,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin( ChatScreen.class ) public class ChatScreenMixin extends Screen @@ -54,8 +53,5 @@ public void onSendMessage( String message, boolean addToHistory, CallbackInfo ci ci.cancel(); return; } - - // Unlike Wurst, this doesn't let you modify the message. - // You shouldn't need to do that anyway. } } diff --git a/src/main/java/me/av306/xenon/mixin/EntityRendererMixin.java b/src/main/java/me/av306/xenon/mixin/EntityRendererMixin.java index 5d08361c..e6b3914c 100644 --- a/src/main/java/me/av306/xenon/mixin/EntityRendererMixin.java +++ b/src/main/java/me/av306/xenon/mixin/EntityRendererMixin.java @@ -16,6 +16,7 @@ @Mixin( EntityRenderer.class ) public class EntityRendererMixin { + @SuppressWarnings( "unchecked" ) @Inject( method = "hasLabel(Lnet/minecraft/entity/Entity;)Z", at = @At( "HEAD" ), @@ -39,7 +40,7 @@ else if ( result == ActionResult.FAIL ) at = @At( value = "LOAD", ordinal = 1 - ) + ) // Target the read of the first local variable (the Text to be rendered) ) private Text modifyLabelText( Text text, T entity, Text textOther, MatrixStack matrices, VertexConsumerProvider vertexConsumerProvider, int light, float tickDelta ) { @@ -50,6 +51,8 @@ private Text modifyLabelText( Text text, T entity, Text textOther, MatrixStack m Text textOverride = EntityRendererEvents.EventData.LABEL_TEXT_OVERRIDE; - return EntityRendererEvents.EventData.SHOULD_OVERRIDE_LABEL_TEXT && textOverride != null ? EntityRendererEvents.EventData.LABEL_TEXT_OVERRIDE : text; + return EntityRendererEvents.EventData.SHOULD_OVERRIDE_LABEL_TEXT && textOverride != null ? + EntityRendererEvents.EventData.LABEL_TEXT_OVERRIDE : + text; } } diff --git a/src/main/java/me/av306/xenon/mixin/GameRendererMixin.java b/src/main/java/me/av306/xenon/mixin/GameRendererMixin.java index ff86ce46..5cf3b30e 100644 --- a/src/main/java/me/av306/xenon/mixin/GameRendererMixin.java +++ b/src/main/java/me/av306/xenon/mixin/GameRendererMixin.java @@ -1,22 +1,19 @@ package me.av306.xenon.mixin; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.llamalad7.mixinextras.sugar.Local; -import me.av306.xenon.Xenon; -import me.av306.xenon.event.EventFields; import me.av306.xenon.event.GameRenderEvents; import me.av306.xenon.event.GetFovEvent; import net.minecraft.client.render.Camera; import net.minecraft.client.render.GameRenderer; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.resource.ResourceManager; import net.minecraft.resource.SynchronousResourceReloader; import net.minecraft.util.ActionResult; import org.joml.Matrix4f; import org.objectweb.asm.Opcodes; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -30,19 +27,11 @@ public abstract class GameRendererMixin implements AutoCloseable, SynchronousRes @Shadow public abstract void reset(); - // FIXME: replace with mixinextras ModifyReturnValue @Inject( at = @At( value = "RETURN", ordinal = 1 ), method = "getFov(Lnet/minecraft/client/render/Camera;FZ)D", cancellable = true ) - - /* - @ModifyReturnValue( - at = @At( value = "RETURN", ordinal = 1 ), - method = "getFov(Lnet/minecraft/client/render/Camera;FZ)D" - ) - */ private void onGetFov( Camera camera, float tickDelta, boolean changingFov, CallbackInfoReturnable cir ) { // Call event @@ -60,24 +49,41 @@ private void onGetFov( Camera camera, float tickDelta, boolean changingFov, Call //Xenon.INSTANCE.sendInfoMessage( String.valueOf( cir.getReturnValue() ) ); } - @Inject( - at = @At( - value = "FIELD", - target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z", - opcode = Opcodes.GETFIELD, - ordinal = 0 - ), - method = "renderWorld(FJ)V", - cancellable = true - ) + @ModifyReturnValue( + at = @At( value = "RETURN", ordinal = 1 ), + method = "getFov(Lnet/minecraft/client/render/Camera;FZ)D" + ) + public double modifyFov( double originalFov ) + { + GetFovEvent.EVENT2.invoker().interact( originalFov ); + + return GetFovEvent.EventData.SHOULD_OVERRIDE_FOV ? + GetFovEvent.EventData.FOV_OVERRIDE : + originalFov / GetFovEvent.EventData.FOV_ZOOM_LEVEL; + } + + + private MatrixStack matrices = new MatrixStack(); + + @Inject( + at = @At( + value = "FIELD", + target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z", + opcode = Opcodes.GETFIELD, + ordinal = 0 + ), // Inject at access of first local variable (TODO: document which one it is) + method = "renderWorld(FJ)V", + cancellable = true + ) private void onRenderWorld( float tickDelta, long finishTimeNanos, CallbackInfo ci, @Local( ordinal = 1 ) Matrix4f matrix4f2 ) // we gotta steal the world matrix { - MatrixStack matrices = new MatrixStack(); + matrices.push(); matrices.multiplyPositionMatrix( matrix4f2 ); ActionResult result = GameRenderEvents.RENDER_WORLD.invoker() .onRenderWorld( tickDelta, finishTimeNanos, matrices ); if ( result == ActionResult.FAIL ) ci.cancel(); + matrices.pop(); } } diff --git a/src/main/java/me/av306/xenon/mixin/RenderSystemMixin.java b/src/main/java/me/av306/xenon/mixin/RenderSystemMixin.java index 34e5af88..07a9ebf3 100644 --- a/src/main/java/me/av306/xenon/mixin/RenderSystemMixin.java +++ b/src/main/java/me/av306/xenon/mixin/RenderSystemMixin.java @@ -1,23 +1,20 @@ package me.av306.xenon.mixin; -import me.av306.xenon.Xenon; import me.av306.xenon.config.GeneralConfigGroup; import com.mojang.blaze3d.systems.RenderSystem; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin( RenderSystem.class ) public class RenderSystemMixin { @ModifyVariable( - at = @At( "HEAD" ), // Idk what this does for now - ordinal = 0, // There's only one argument - size + at = @At( "HEAD" ), + ordinal = 0, method = "renderCrosshair(I)V", argsOnly = true - ) + ) // Target the very first local variable - the crosshair size private static int onRenderDebugCrosshair( int size ) { // This method name is a bit misleading diff --git a/src/main/java/me/av306/xenon/packets/OptInPacketPayload.java b/src/main/java/me/av306/xenon/packets/OptInPacketPayload.java new file mode 100644 index 00000000..6fccc038 --- /dev/null +++ b/src/main/java/me/av306/xenon/packets/OptInPacketPayload.java @@ -0,0 +1,18 @@ +package me.av306.xenon.packets; + +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.codec.PacketCodecs; +import net.minecraft.network.packet.CustomPayload; + +public record OptInPacketPayload( String featureName ) implements CustomPayload +{ + public static final Id ID = CustomPayload.id( "xenon:opt_in" ); + public static final PacketCodec CODEC = PacketCodec.tuple( PacketCodecs.STRING, OptInPacketPayload::featureName, OptInPacketPayload::new ); + + @Override + public Id getId() { + return ID; + } + +} diff --git a/src/main/java/me/av306/xenon/packets/OptOutPacketPayload.java b/src/main/java/me/av306/xenon/packets/OptOutPacketPayload.java new file mode 100644 index 00000000..08e50bfb --- /dev/null +++ b/src/main/java/me/av306/xenon/packets/OptOutPacketPayload.java @@ -0,0 +1,18 @@ +package me.av306.xenon.packets; + +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.codec.PacketCodecs; +import net.minecraft.network.packet.CustomPayload; + +public record OptOutPacketPayload( String featureName ) implements CustomPayload +{ + public static final Id ID = CustomPayload.id( "xenon:opt_out" ); + public static final PacketCodec CODEC = PacketCodec.tuple( PacketCodecs.STRING, OptOutPacketPayload::featureName, OptOutPacketPayload::new ); + + @Override + public Id getId() { + return ID; + } + +} diff --git a/src/main/resources/assets/xenon/lang/en_us.json b/src/main/resources/assets/xenon/lang/en_us.json index 56b41be4..7421e01f 100644 --- a/src/main/resources/assets/xenon/lang/en_us.json +++ b/src/main/resources/assets/xenon/lang/en_us.json @@ -158,7 +158,7 @@ "text.xenon.ifeature.configchange.success": "Successfully changed config \"%s\" to value %s!", "text.xenon.ifeature.executeaction.fail": "Failed to execute action: %s", "text.xenon.ifeature.executeaction.success": "Successfully executed action: %s", - "text.xenon.ifeature.forcedisabled": "The feature has been disabled by the server.", + "text.xenon.ifeature.blocked": "Feature \"%s\" is blocked.", "text.xenon.ifeature.help": "[%s] %s", "text.xenon.itoggleablefeature.enabled": "%s ENABLED!", "text.xenon.itoggleablefeature.disabled": "%s DISABLED!",