diff --git a/build.gradle.kts b/build.gradle.kts index 1a343f3..f336f1f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,9 +1,6 @@ -@file:Suppress("LocalVariableName") - plugins { - id("com.github.johnrengelman.shadow") - id("com.gladed.androidgitversion") - id("fabric-loom") + alias(libs.plugins.android.git.version) + alias(libs.plugins.fabric.loom) `java-library` } @@ -15,47 +12,38 @@ androidGitVersion { group = "arm32x.minecraft" version = androidGitVersion.name() -configurations.implementation.get().extendsFrom(configurations["shadow"]) - repositories { mavenCentral() } dependencies { - val minecraft_version: String by project - minecraft("com.mojang:minecraft:$minecraft_version") - val yarn_mappings: String by project - mappings("net.fabricmc:yarn:$yarn_mappings:v2") - val loader_version: String by project - modImplementation("net.fabricmc:fabric-loader:$loader_version") + minecraft(libs.minecraft) - val fabric_version: String by project - modImplementation("net.fabricmc.fabric-api:fabric-api:$fabric_version") + implementation(libs.fabric.loader) + implementation(libs.fabric.api) - val msgpack_java_version: String by project - shadow("org.msgpack:msgpack-core:${msgpack_java_version}") + implementation(libs.msgpack.core) + include(libs.msgpack.core) - val junit_version: String by project - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junit_version}") - val jqwik_version: String by project - testImplementation("net.jqwik:jqwik:${jqwik_version}") - val assertj_version: String by project - testImplementation("org.assertj:assertj-core:${assertj_version}") + testRuntimeOnly(libs.junit.jupiter.engine) + testImplementation(libs.jqwik) + testImplementation(libs.assertj.core) } java { toolchain { - languageVersion.set(JavaLanguageVersion.of(21)) + languageVersion.set(JavaLanguageVersion.of(libs.versions.java.get().toInt())) } withSourcesJar() } -tasks.withType { +tasks.withType().configureEach { options.encoding = "UTF-8" + options.release.set(libs.versions.java.get().toInt()) } loom { - accessWidenerPath.set(File("src/main/resources/commandblockide.accesswidener")) + accessWidenerPath.set(file("src/main/resources/commandblockide.accesswidener")) } tasks.processResources { @@ -66,24 +54,17 @@ tasks.processResources { } } -// Reproducible builds (or at least an attempt) -tasks.withType { +tasks.withType().configureEach { isPreserveFileTimestamps = false isReproducibleFileOrder = true } tasks.jar { - from("LICENSE") -} - -tasks.shadowJar { - configurations = listOf(project.configurations.shadow.get()) + from("LICENSE") { + rename { "${it}_${project.name}" } + } } -tasks.remapJar { - dependsOn(tasks.shadowJar) - inputFile.set(tasks.shadowJar.get().archiveFile) - doLast { - tasks.shadowJar.get().archiveFile.get().asFile.delete() - } +tasks.test { + useJUnitPlatform() } diff --git a/gradle.properties b/gradle.properties index f2cd455..190dc7b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,19 +1,3 @@ -# Done to increase the memory available to gradle. org.gradle.jvmargs=-Xmx2G -# Gradle Plugins -android_git_version_version=0.4.14 -loom_version=1.13.3 -shadow_version=7.1.2 -# Fabric Properties -# check these on https://modmuss50.me/fabric.html -minecraft_version=1.21.11 -yarn_mappings=1.21.11+build.4 -loader_version=0.18.4 -# Dependencies -# check these on https://modmuss50.me/fabric.html -fabric_version=0.141.1+1.21.11 -msgpack_java_version=0.9.3 -# Test dependencies -junit_version=5.9.2 -jqwik_version=1.7.3 -assertj_version=3.24.2 +org.gradle.parallel=true +org.gradle.configuration-cache=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..16ecb3e --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,28 @@ +[versions] +java = "25" +minecraft = "26.1.2" + +fabric-api = "0.151.0+26.1.2" +fabric-loader = "0.19.3" +fabric-loom = "1.16-SNAPSHOT" + +jqwik = "1.7.3" +junit-jupiter = "5.9.2" +android-git-version = "0.4.14" +msgpack-core = "0.9.12" +assertj-core = "3.24.2" + +[libraries] +minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" } + +fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric-api" } +fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-loader" } + +jqwik = { module = "net.jqwik:jqwik", version.ref = "jqwik" } +junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit-jupiter" } +msgpack-core = { module = "org.msgpack:msgpack-core", version.ref = "msgpack-core" } +assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertj-core" } + +[plugins] +fabric-loom = { id = "net.fabricmc.fabric-loom", version.ref = "fabric-loom" } +android-git-version = { id = "com.gladed.androidgitversion", version.ref = "android-git-version" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3ae1e2f..9937dae 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index 615ed17..5309582 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,3 @@ -@file:Suppress("LocalVariableName") - pluginManagement { repositories { maven { @@ -8,15 +6,6 @@ pluginManagement { } gradlePluginPortal() } - plugins { - val android_git_version_version: String by settings - val loom_version: String by settings - val shadow_version: String by settings - - id("com.github.johnrengelman.shadow") version shadow_version - id("com.gladed.androidgitversion") version android_git_version_version - id("fabric-loom") version loom_version - } } rootProject.name = "command-block-ide" diff --git a/src/main/java/arm32x/minecraft/commandblockide/CommandBlockIDE.java b/src/main/java/arm32x/minecraft/commandblockide/CommandBlockIDE.java index e418ccc..081008b 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/CommandBlockIDE.java +++ b/src/main/java/arm32x/minecraft/commandblockide/CommandBlockIDE.java @@ -12,15 +12,15 @@ import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.command.permission.Permission; -import net.minecraft.command.permission.PermissionLevel; -import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.permissions.Permission; +import net.minecraft.server.permissions.PermissionLevel; +import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.function.CommandFunction; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.functions.CommandFunction; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -31,38 +31,38 @@ public void onInitialize() { EditFunctionCommand.register(dispatcher)); final PacketMerger functionMerger = new PacketMerger(); - PayloadTypeRegistry.playC2S().register(Packets.APPLY_FUNCTION, ApplyFunctionPayload.CODEC); + PayloadTypeRegistry.serverboundPlay().register(Packets.APPLY_FUNCTION, ApplyFunctionPayload.CODEC); ServerPlayNetworking.registerGlobalReceiver(Packets.APPLY_FUNCTION, (payload, context) -> { - if (!context.player().getPermissions().hasPermission(new Permission.Level(PermissionLevel.GAMEMASTERS))) { + if (!context.player().permissions().hasPermission(new Permission.HasCommandLevel(PermissionLevel.GAMEMASTERS))) { return; } - Optional maybeMerged = Optional.empty(); + Optional maybeMerged = Optional.empty(); try { maybeMerged = functionMerger.append(payload.toBuf()); } catch (PacketMerger.InvalidSplitPacketException e) { LOGGER.error("PacketMerger", e); } if (maybeMerged.isPresent()) { - PacketByteBuf merged = maybeMerged.get(); + FriendlyByteBuf merged = maybeMerged.get(); Identifier functionId = merged.readIdentifier(); int lineCount = merged.readVarInt(); String[] lines = new String[lineCount]; for (int index = 0; index < lineCount; index++) { - lines[index] = merged.readString(Integer.MAX_VALUE >> 2); + lines[index] = merged.readUtf(Integer.MAX_VALUE >> 2); } - ServerPlayerEntity player = context.player(); + ServerPlayer player = context.player(); MinecraftServer server = context.server(); server.execute(() -> { - Text feedbackMessage = FunctionIO.saveFunction(server, functionId, Arrays.asList(lines)); - player.sendMessage(feedbackMessage); + Component feedbackMessage = FunctionIO.saveFunction(server, functionId, Arrays.asList(lines)); + player.sendSystemMessage(feedbackMessage); }); } }); } private static void updateFunctionLines(MinecraftServer server, Identifier functionId, List lines) { - Optional> maybeFunction = server.getCommandFunctionManager().getFunction(functionId); + Optional> maybeFunction = server.getFunctions().get(functionId); maybeFunction.ifPresent(function -> ((CommandFunctionExtension)function).ide$setOriginalLines(lines)); } diff --git a/src/main/java/arm32x/minecraft/commandblockide/Packets.java b/src/main/java/arm32x/minecraft/commandblockide/Packets.java index 445f125..9a72054 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/Packets.java +++ b/src/main/java/arm32x/minecraft/commandblockide/Packets.java @@ -3,17 +3,17 @@ import arm32x.minecraft.commandblockide.payloads.ApplyFunctionPayload; import arm32x.minecraft.commandblockide.payloads.EditFunctionPayload; import arm32x.minecraft.commandblockide.payloads.UpdateFunctionCommandPayload; -import net.minecraft.network.packet.CustomPayload.Id; -import net.minecraft.util.Identifier; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload.Type; +import net.minecraft.resources.Identifier; public final class Packets { // Namespace private static final String NAMESPACE = "commandblockide"; // Client to Server - public static final Id APPLY_FUNCTION = new Id<>(Identifier.of(NAMESPACE + ":apply_function")); + public static final Type APPLY_FUNCTION = new Type<>(Identifier.parse(NAMESPACE + ":apply_function")); // Server to Client - public static final Id EDIT_FUNCTION = new Id<>(Identifier.of(NAMESPACE + ":edit_function")); - public static final Id UPDATE_FUNCTION_COMMAND = new Id<>(Identifier.of(NAMESPACE + ":update_function_command")); + public static final Type EDIT_FUNCTION = new Type<>(Identifier.parse(NAMESPACE + ":edit_function")); + public static final Type UPDATE_FUNCTION_COMMAND = new Type<>(Identifier.parse(NAMESPACE + ":update_function_command")); } diff --git a/src/main/java/arm32x/minecraft/commandblockide/client/CommandBlockIDEClient.java b/src/main/java/arm32x/minecraft/commandblockide/client/CommandBlockIDEClient.java index df4592a..f6493b6 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/client/CommandBlockIDEClient.java +++ b/src/main/java/arm32x/minecraft/commandblockide/client/CommandBlockIDEClient.java @@ -9,9 +9,9 @@ import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.FatalErrorScreen; -import net.minecraft.text.Text; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.ErrorScreen; +import net.minecraft.network.chat.Component; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; @@ -20,16 +20,16 @@ public final class CommandBlockIDEClient implements ClientModInitializer { @Override public void onInitializeClient() { - PayloadTypeRegistry.playS2C().register(Packets.EDIT_FUNCTION, EditFunctionPayload.CODEC); + PayloadTypeRegistry.clientboundPlay().register(Packets.EDIT_FUNCTION, EditFunctionPayload.CODEC); ClientPlayNetworking.registerGlobalReceiver(Packets.EDIT_FUNCTION, (payload, context) -> { - MinecraftClient client = context.client(); + Minecraft client = context.client(); client.execute(() -> client.setScreen(new CommandFunctionIDEScreen(payload.id(), payload.lineCount()))); }); - PayloadTypeRegistry.playS2C().register(Packets.UPDATE_FUNCTION_COMMAND, UpdateFunctionCommandPayload.CODEC); + PayloadTypeRegistry.clientboundPlay().register(Packets.UPDATE_FUNCTION_COMMAND, UpdateFunctionCommandPayload.CODEC); ClientPlayNetworking.registerGlobalReceiver(Packets.UPDATE_FUNCTION_COMMAND, (payload, context) -> { - MinecraftClient client = context.client(); + Minecraft client = context.client(); client.execute(() -> { - if (client.currentScreen instanceof CommandFunctionIDEScreen ide) { + if (client.screen instanceof CommandFunctionIDEScreen ide) { ide.update(payload.index(), payload.line()); } }); @@ -42,9 +42,9 @@ public static void showErrorScreen(Exception ex, @Nullable String currentAction) } else { LOGGER.error("Error screen shown:", ex); } - MinecraftClient.getInstance().setScreen(new FatalErrorScreen( - Text.translatable(currentAction != null ? "commandBlockIDE.errorWithContext" : "commandBlockIDE.error", currentAction), - Text.literal(ex.toString()) + Minecraft.getInstance().setScreen(new ErrorScreen( + Component.translatable(currentAction != null ? "commandBlockIDE.errorWithContext" : "commandBlockIDE.error", currentAction), + Component.literal(ex.toString()) )); } diff --git a/src/main/java/arm32x/minecraft/commandblockide/client/CommandChainTracer.java b/src/main/java/arm32x/minecraft/commandblockide/client/CommandChainTracer.java index d0fad47..b8d234c 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/client/CommandChainTracer.java +++ b/src/main/java/arm32x/minecraft/commandblockide/client/CommandChainTracer.java @@ -2,17 +2,17 @@ import java.util.*; import java.util.stream.Stream; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.CommandBlock; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.CommandBlock; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; public final class CommandChainTracer { - private final ClientWorld world; + private final ClientLevel world; - public CommandChainTracer(ClientWorld world) { + public CommandChainTracer(ClientLevel world) { this.world = world; } @@ -48,14 +48,14 @@ private Forwards(BlockPos startPosition) { public boolean hasNext() { BlockState blockState = world.getBlockState(position); if (isCommandBlock(blockState)) { - Direction facing = blockState.get(CommandBlock.FACING); - BlockPos nextPosition = position.offset(facing); + Direction facing = blockState.getValue(CommandBlock.FACING); + BlockPos nextPosition = position.relative(facing); BlockState nextBlockState = world.getBlockState(nextPosition); return Stream.of( Blocks.COMMAND_BLOCK, Blocks.REPEATING_COMMAND_BLOCK, Blocks.CHAIN_COMMAND_BLOCK - ).anyMatch(nextBlockState::isOf) && !visited.contains(nextPosition); + ).anyMatch(nextBlockState::is) && !visited.contains(nextPosition); } return false; } @@ -64,14 +64,14 @@ public boolean hasNext() { public BlockPos next() { BlockState blockState = world.getBlockState(position); if (isCommandBlock(blockState)) { - Direction facing = blockState.get(CommandBlock.FACING); - BlockPos nextPosition = position.offset(facing); + Direction facing = blockState.getValue(CommandBlock.FACING); + BlockPos nextPosition = position.relative(facing); BlockState nextBlockState = world.getBlockState(nextPosition); if (Stream.of( Blocks.COMMAND_BLOCK, Blocks.REPEATING_COMMAND_BLOCK, Blocks.CHAIN_COMMAND_BLOCK - ).anyMatch(nextBlockState::isOf) && !visited.contains(nextPosition)) { + ).anyMatch(nextBlockState::is) && !visited.contains(nextPosition)) { position = nextPosition; visited.add(position); return position; @@ -97,7 +97,7 @@ public boolean hasNext() { Blocks.COMMAND_BLOCK, Blocks.REPEATING_COMMAND_BLOCK, Blocks.CHAIN_COMMAND_BLOCK - ).anyMatch(blockState::isOf)) { + ).anyMatch(blockState::is)) { long resultCount = getStream(blockState).count(); return resultCount == 1; } @@ -111,7 +111,7 @@ public BlockPos next() { Blocks.COMMAND_BLOCK, Blocks.REPEATING_COMMAND_BLOCK, Blocks.CHAIN_COMMAND_BLOCK - ).anyMatch(blockState::isOf)) { + ).anyMatch(blockState::is)) { List results = getStream(blockState).toList(); if (results.size() != 1) { throw new NoSuchElementException(); @@ -125,15 +125,15 @@ public BlockPos next() { private Stream getStream(BlockState blockState) { return Stream.of(Direction.values()) - .filter((direction) -> direction != blockState.get(CommandBlock.FACING)) - .map((direction) -> position.offset(direction)) + .filter((direction) -> direction != blockState.getValue(CommandBlock.FACING)) + .map((direction) -> position.relative(direction)) .filter((pos) -> isCommandBlock(world.getBlockState(pos)) && !visited.contains(pos)) - .filter((pos) -> pos.offset(world.getBlockState(pos).get(CommandBlock.FACING)).equals(position)); + .filter((pos) -> pos.relative(world.getBlockState(pos).getValue(CommandBlock.FACING)).equals(position)); } } // TODO: Move to a proper utility class. public static boolean isCommandBlock(BlockState blockState) { - return blockState.isOf(Blocks.COMMAND_BLOCK) || blockState.isOf(Blocks.REPEATING_COMMAND_BLOCK) || blockState.isOf(Blocks.CHAIN_COMMAND_BLOCK); + return blockState.is(Blocks.COMMAND_BLOCK) || blockState.is(Blocks.REPEATING_COMMAND_BLOCK) || blockState.is(Blocks.CHAIN_COMMAND_BLOCK); } } diff --git a/src/main/java/arm32x/minecraft/commandblockide/client/gui/Container.java b/src/main/java/arm32x/minecraft/commandblockide/client/gui/Container.java index 72ca11a..c46e0a1 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/client/gui/Container.java +++ b/src/main/java/arm32x/minecraft/commandblockide/client/gui/Container.java @@ -4,33 +4,38 @@ import java.util.Comparator; import java.util.List; import net.minecraft.client.gui.*; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.components.Renderable; +import net.minecraft.client.gui.components.events.AbstractContainerEventHandler; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.gui.narration.NarratableEntry; -public abstract class Container extends AbstractParentElement implements Drawable, Selectable { - protected final List children = new ArrayList<>(); - protected final List selectables = new ArrayList<>(); - protected final List drawables = new ArrayList<>(); +public abstract class Container extends AbstractContainerEventHandler implements Renderable, NarratableEntry { + protected final List children = new ArrayList<>(); + protected final List selectables = new ArrayList<>(); + protected final List drawables = new ArrayList<>(); - protected T addDrawableChild(T child) { + protected T addDrawableChild(T child) { drawables.add(child); return addSelectableChild(child); } - protected T addDrawable(T drawable) { + protected T addDrawable(T drawable) { drawables.add(drawable); return drawable; } - protected T addSelectableChild(T child) { + protected T addSelectableChild(T child) { children.add(child); selectables.add(child); return child; } - protected void remove(Element child) { - if (child instanceof Drawable) { + protected void remove(GuiEventListener child) { + if (child instanceof Renderable) { drawables.remove(child); } - if (child instanceof Selectable) { + if (child instanceof NarratableEntry) { selectables.remove(child); } children.remove(child); @@ -43,20 +48,20 @@ protected void clearChildren() { } @Override - public SelectionType getType() { + public NarrationPriority narrationPriority() { return selectables.stream() - .map(Selectable::getType) + .map(NarratableEntry::narrationPriority) .max(Comparator.naturalOrder()) - .orElse(SelectionType.NONE); + .orElse(NarrationPriority.NONE); } @Override - public List children() { return children; } + public List children() { return children; } @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { - for (Drawable drawable : drawables) { - drawable.render(context, mouseX, mouseY, delta); + public void extractRenderState(GuiGraphicsExtractor context, int mouseX, int mouseY, float delta) { + for (Renderable drawable : drawables) { + drawable.extractRenderState(context, mouseX, mouseY, delta); } } } diff --git a/src/main/java/arm32x/minecraft/commandblockide/client/gui/MultilineTextFieldWidget.java b/src/main/java/arm32x/minecraft/commandblockide/client/gui/MultilineTextFieldWidget.java index 92031d9..a453dd6 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/client/gui/MultilineTextFieldWidget.java +++ b/src/main/java/arm32x/minecraft/commandblockide/client/gui/MultilineTextFieldWidget.java @@ -1,7 +1,7 @@ package arm32x.minecraft.commandblockide.client.gui; +import arm32x.minecraft.commandblockide.mixin.client.MultilineTextFieldAccessor; import arm32x.minecraft.commandblockide.mixin.client.EditBoxAccessor; -import arm32x.minecraft.commandblockide.mixin.client.TextFieldWidgetAccessor; import arm32x.minecraft.commandblockide.util.OrderedTexts; import java.util.Arrays; import java.util.List; @@ -10,32 +10,32 @@ import java.util.function.Predicate; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gl.RenderPipelines; -import net.minecraft.client.gui.Click; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.EditBox; -import net.minecraft.client.gui.cursor.StandardCursors; -import net.minecraft.client.gui.screen.ChatInputSuggestor; -import net.minecraft.client.gui.widget.TextFieldWidget; -import net.minecraft.client.input.CursorMovement; -import net.minecraft.client.input.KeyInput; -import net.minecraft.text.OrderedText; -import net.minecraft.text.Style; -import net.minecraft.text.Text; +import net.minecraft.client.gui.Font; +import net.minecraft.client.renderer.RenderPipelines; +import net.minecraft.client.input.MouseButtonEvent; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.components.MultilineTextField; +import com.mojang.blaze3d.platform.cursor.CursorTypes; +import net.minecraft.client.gui.components.CommandSuggestions; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.components.Whence; +import net.minecraft.client.input.KeyEvent; +import net.minecraft.util.FormattedCharSequence; +import net.minecraft.network.chat.Style; +import net.minecraft.network.chat.Component; import net.minecraft.util.Util; -import net.minecraft.util.math.MathHelper; +import net.minecraft.util.Mth; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; @Environment(EnvType.CLIENT) -public class MultilineTextFieldWidget extends TextFieldWidget { +public class MultilineTextFieldWidget extends EditBox { /** * Allows easy and convenient access to private fields in the superclass. */ - private final TextFieldWidgetAccessor self = (TextFieldWidgetAccessor)this; + private final EditBoxAccessor self = (EditBoxAccessor)this; // TODO: Allow the user to configure this or to indent with tabs. // Note that both the text field renderer and the command processor do not @@ -46,7 +46,7 @@ public class MultilineTextFieldWidget extends TextFieldWidget { // invisible before switching to the other state. private static final long CURSOR_BLINK_INTERVAL_MS = 300; - private final EditBox editBox; + private final MultilineTextField editBox; private boolean horizontalScrollEnabled; private int horizontalScroll = 0; @@ -59,18 +59,18 @@ public class MultilineTextFieldWidget extends TextFieldWidget { private @Nullable Runnable cursorChangeListener = null; - public MultilineTextFieldWidget(TextRenderer textRenderer, int x, int y, int width, int height, Text text, boolean horizontalScrollEnabled, boolean verticalScrollEnabled) { + public MultilineTextFieldWidget(Font textRenderer, int x, int y, int width, int height, Component text, boolean horizontalScrollEnabled, boolean verticalScrollEnabled) { super(textRenderer, x, y, width, height, text); this.horizontalScrollEnabled = horizontalScrollEnabled; this.verticalScrollEnabled = verticalScrollEnabled; // TODO: Support soft wrap. - editBox = new EditBox(textRenderer, Integer.MAX_VALUE); + editBox = new MultilineTextField(textRenderer, Integer.MAX_VALUE); } - public MultilineTextFieldWidget(TextRenderer textRenderer, int x, int y, int width, int height, Text text) { + public MultilineTextFieldWidget(Font textRenderer, int x, int y, int width, int height, Component text) { this(textRenderer, x, y, width, height, text, true, true); - editBox.setCursorChangeListener(() -> { + editBox.setCursorListener(() -> { scrollToEnsureCursorVisible(); if (cursorChangeListener != null) { cursorChangeListener.run(); @@ -79,8 +79,8 @@ public MultilineTextFieldWidget(TextRenderer textRenderer, int x, int y, int wid } @Override - public void setChangedListener(@Nullable Consumer changedListener) { - editBox.setChangeListener(Objects.requireNonNullElseGet(changedListener, () -> text -> {})); + public void setResponder(@Nullable Consumer changedListener) { + editBox.setValueListener(Objects.requireNonNullElseGet(changedListener, () -> text -> {})); } public void setCursorChangeListener(@Nullable Runnable cursorChangeListener) { @@ -88,28 +88,23 @@ public void setCursorChangeListener(@Nullable Runnable cursorChangeListener) { } @Override - public void setText(String text) { - editBox.setText(text); + public void setValue(String text) { + editBox.setValue(text); } @Override - public String getText() { - return editBox.getText(); + public String getValue() { + return editBox.value(); } @Override - public String getSelectedText() { + public String getHighlighted() { return editBox.getSelectedText(); } - @Override - public void setTextPredicate(Predicate textPredicate) { - throw new UnsupportedOperationException(); - } - @Override @Deprecated - public void addFormatter(TextFieldWidget.Formatter formatter) { + public void addFormatter(EditBox.TextFormatter formatter) { // Do nothing, since we use our own syntax highlighting system. I would // love to throw an UnsupportedOperationException, but this is called by // ChatInputSuggestor. @@ -124,41 +119,41 @@ public void setSyntaxHighlighter(SyntaxHighlighter syntaxHighlighter) { } @Override - public void write(String text) { - editBox.replaceSelection(text); + public void insertText(String text) { + editBox.insertText(text); } @Override - public void eraseWords(int wordOffset) { + public void deleteWords(int wordOffset) { throw new UnsupportedOperationException(); } @Override - public void eraseCharacters(int characterOffset) { - editBox.delete(characterOffset); + public void deleteChars(int characterOffset) { + editBox.deleteText(characterOffset); } @Override - public int getWordSkipPosition(int wordOffset) { + public int getWordPosition(int wordOffset) { throw new UnsupportedOperationException(); } @Override public void moveCursor(int offset, boolean hasShiftDown) { editBox.setSelecting(hasShiftDown); - editBox.moveCursor(CursorMovement.RELATIVE, offset); + editBox.seekCursor(Whence.RELATIVE, offset); } private void moveCursor(double mouseX, double mouseY, boolean hasShiftDown) { double virtualX = mouseX - getInnerX() + getHorizontalScroll(); double virtualY = mouseY - getInnerY() + getVerticalScroll(); - int lineIndex = MathHelper.floor(virtualY / getLineHeight()); + int lineIndex = Mth.floor(virtualY / getLineHeight()); // Get a rough estimate of where the cursor should be. - EditBox.Substring lineSubstring = editBox.getLine(lineIndex); - String line = getText().substring(lineSubstring.beginIndex(), lineSubstring.endIndex()); - int charIndexInLine = self.getTextRenderer().trimToWidth(line, MathHelper.floor(virtualX)).length(); + MultilineTextField.StringView lineSubstring = editBox.getLineView(lineIndex); + String line = getValue().substring(lineSubstring.beginIndex(), lineSubstring.endIndex()); + int charIndexInLine = self.getFont().plainSubstrByWidth(line, Mth.floor(virtualX)).length(); int charIndex = lineSubstring.beginIndex() + charIndexInLine; // Refine the estimate by determining the nearest character boundary. @@ -168,67 +163,67 @@ private void moveCursor(double mouseX, double mouseY, boolean hasShiftDown) { charIndex++; } - setCursor(charIndex, hasShiftDown); + moveCursorTo(charIndex, hasShiftDown); } @Override - public void setCursor(int cursor, boolean hasShiftDown) { + public void moveCursorTo(int cursor, boolean hasShiftDown) { editBox.setSelecting(hasShiftDown); - editBox.moveCursor(CursorMovement.ABSOLUTE, cursor); + editBox.seekCursor(Whence.ABSOLUTE, cursor); } @Override - public void setSelectionStart(int cursor) { - setCursor(cursor, true); + public void setCursorPosition(int cursor) { + moveCursorTo(cursor, true); } @Override - public void setSelectionEnd(int index) { - ((EditBoxAccessor)editBox).setSelectionEnd(index); + public void setHighlightPos(int index) { + ((MultilineTextFieldAccessor)editBox).setSelectCursor(index); } @Override - public boolean keyPressed(KeyInput input) { + public boolean keyPressed(KeyEvent input) { if (input.key() == GLFW.GLFW_KEY_TAB) { if (editBox.hasSelection()) { logger.warn("Indenting selected lines is not yet supported"); } else { - int cursorLeft = getCursor() - getLineStartBefore(getCursor()); + int cursorLeft = getCursorPosition() - getLineStartBefore(getCursorPosition()); String indent = " ".repeat(4 - cursorLeft % INDENT_SIZE); - editBox.replaceSelection(indent); + editBox.insertText(indent); } return true; } else { - return editBox.handleSpecialKey(input); + return editBox.keyPressed(input); } } @Override - public boolean mouseClicked(Click click, boolean doubled) { + public boolean mouseClicked(MouseButtonEvent click, boolean doubled) { if (!this.isVisible()) { return false; } - if (self.isFocusUnlocked()) { + if (self.isCanLoseFocus()) { setFocused(isMouseOver(click.x(), click.y())); } if (isFocused() && isMouseOver(click.x(), click.y()) && click.button() == 0) { - moveCursor(click.x(), click.y(), click.hasShift()); + moveCursor(click.x(), click.y(), click.hasShiftDown()); return true; } return false; } @Override - public boolean mouseDragged(Click click, double offsetX, double offsetY) { + public boolean mouseDragged(MouseButtonEvent click, double offsetX, double offsetY) { if (!this.isVisible()) { return false; } - if (self.isFocusUnlocked()) { + if (self.isCanLoseFocus()) { setFocused(isMouseOver(click.x(), click.y())); } if (isFocused() && isMouseOver(click.x(), click.y()) && click.button() == 0) { moveCursor(click.x(), click.y(), true); - editBox.setSelecting(click.hasShift()); + editBox.setSelecting(click.hasShiftDown()); return true; } return false; @@ -251,14 +246,14 @@ public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmou } @Override - public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + public void extractWidgetRenderState(GuiGraphicsExtractor context, int mouseX, int mouseY, float delta) { if (!isVisible()) { return; } - if (drawsBackground()) { - var textureId = TextFieldWidgetAccessor.getTextures().get(isInteractable(), isFocused()); - context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, textureId, getX(), getY(), getWidth(), getHeight()); + if (isBordered()) { + var textureId = EditBoxAccessor.getTextures().get(isActive(), isFocused()); + context.blitSprite(RenderPipelines.GUI_TEXTURED, textureId, getX(), getY(), getWidth(), getHeight()); } context.enableScissor( @@ -268,41 +263,41 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY, float delt this.getY() + this.getHeight() - 1 ); - int textColor = self.invokeIsEditable() ? self.getEditableColor() : self.getUneditableColor(); + int textColor = self.invokeIsEditable() ? self.getTextColor() : self.getTextColorUneditable(); int x = getInnerX() - horizontalScroll; int y = getInnerY() - verticalScroll; - long timeSinceLastSwitchFocusMs = Util.getMeasuringTimeMs() - self.getLastSwitchFocusTime(); + long timeSinceLastSwitchFocusMs = Util.getMillis() - self.getFocusedTime(); boolean showCursor = isFocused() && timeSinceLastSwitchFocusMs / CURSOR_BLINK_INTERVAL_MS % 2 == 0; - boolean lineCursor = getCursor() < getText().length() || getText().length() >= self.invokeGetMaxLength(); + boolean lineCursor = getCursorPosition() < getValue().length() || getValue().length() >= self.invokeGetMaxLength(); int cursorLine = getCurrentLineIndex(); int cursorY = y + lineHeight * cursorLine; - List lines = getSyntaxHighlighter().highlight(getText()); + List lines = getSyntaxHighlighter().highlight(getValue()); for (int index = 0; index < lines.size(); index++) { - OrderedText line = lines.get(index); - context.drawTextWithShadow(self.getTextRenderer(), line, x, y + lineHeight * index, textColor); + FormattedCharSequence line = lines.get(index); + context.text(self.getFont(), line, x, y + lineHeight * index, textColor); } if (showCursor) { // Figure out the cursor X position by measuring the text before it. // This assumes that the highlighter returns the same characters as // the original text, which is not enforced by the API. - int indexOfLastNewlineBeforeCursor = getLineStartBefore(getCursor()) - 1; + int indexOfLastNewlineBeforeCursor = getLineStartBefore(getCursorPosition()) - 1; int codePointsBeforeCursor; if (indexOfLastNewlineBeforeCursor != -1) { - codePointsBeforeCursor = getText().codePointCount(indexOfLastNewlineBeforeCursor, Math.max(getCursor() - 1, 0)); + codePointsBeforeCursor = getValue().codePointCount(indexOfLastNewlineBeforeCursor, Math.max(getCursorPosition() - 1, 0)); } else { - codePointsBeforeCursor = getText().codePointCount(0, getCursor()); + codePointsBeforeCursor = getValue().codePointCount(0, getCursorPosition()); } - OrderedText textBeforeCursor = OrderedTexts.limit(codePointsBeforeCursor, lines.get(cursorLine)); - int cursorX = x + self.getTextRenderer().getWidth(textBeforeCursor) - 1; + FormattedCharSequence textBeforeCursor = OrderedTexts.limit(codePointsBeforeCursor, lines.get(cursorLine)); + int cursorX = x + self.getFont().width(textBeforeCursor) - 1; if (lineCursor) { context.fill(cursorX, cursorY - 1, cursorX + 1, cursorY + 10, 0xFFD0D0D0); } else { - context.drawTextWithShadow(self.getTextRenderer(), "_", cursorX + 1, cursorY, textColor); + context.text(self.getFont(), "_", cursorX + 1, cursorY, textColor); } } @@ -313,18 +308,18 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY, float delt context.disableScissor(); if (isHovered()) { - context.setCursor(StandardCursors.IBEAM); + context.requestCursor(CursorTypes.IBEAM); } } - private void renderSelection(DrawContext context, int x, int y) { - var selection = editBox.getSelection(); + private void renderSelection(GuiGraphicsExtractor context, int x, int y) { + var selection = editBox.getSelected(); int normalizedSelectionStart = selection.beginIndex(); int normalizedSelectionEnd = selection.endIndex(); - int startX = x + self.getTextRenderer().getWidth(getText().substring(getLineStartBefore(normalizedSelectionStart), normalizedSelectionStart)) - 1; + int startX = x + self.getFont().width(getValue().substring(getLineStartBefore(normalizedSelectionStart), normalizedSelectionStart)) - 1; int startY = y + lineHeight * getLineIndex(normalizedSelectionStart) - 1; - int endX = x + self.getTextRenderer().getWidth(getText().substring(getLineStartBefore(normalizedSelectionEnd), normalizedSelectionEnd)) - 1; + int endX = x + self.getFont().width(getValue().substring(getLineStartBefore(normalizedSelectionEnd), normalizedSelectionEnd)) - 1; int endY = y + lineHeight * getLineIndex(normalizedSelectionEnd) - 1; int leftEdge = getInnerX() - 1; @@ -332,26 +327,26 @@ private void renderSelection(DrawContext context, int x, int y) { if (startY == endY) { // Selection spans one line - context.drawSelection(startX, startY, endX, endY + lineHeight - 1, true); + context.textHighlight(startX, startY, endX, endY + lineHeight - 1, true); } else { // Selection spans two or more lines - context.drawSelection(startX, startY, rightEdge, startY + lineHeight, true); + context.textHighlight(startX, startY, rightEdge, startY + lineHeight, true); if (!(startY - lineHeight == endY || endY - lineHeight == startY)) { // Selection spans three or more lines - context.drawSelection(leftEdge, startY + lineHeight, rightEdge, endY, true); + context.textHighlight(leftEdge, startY + lineHeight, rightEdge, endY, true); } - context.drawSelection(leftEdge, endY, endX, endY + lineHeight - 1, true); + context.textHighlight(leftEdge, endY, endX, endY + lineHeight - 1, true); } } @Override public void setMaxLength(int maxLength) { - editBox.setMaxLength(maxLength); + editBox.setCharacterLimit(maxLength); } @Override - public int getCursor() { - return editBox.getCursor(); + public int getCursorPosition() { + return editBox.cursor(); } public int getLineCount() { @@ -359,11 +354,11 @@ public int getLineCount() { } public int getCurrentLineIndex() { - return getLineIndex(getCursor()); + return getLineIndex(getCursorPosition()); } private int getLineIndex(int charIndex) { - return (int)getText() + return (int) getValue() .substring(0, charIndex) .codePoints() .filter(point -> point == '\n') @@ -371,20 +366,20 @@ private int getLineIndex(int charIndex) { } private int getLineStartBefore(int charIndex) { - return getText().lastIndexOf('\n', Math.max(charIndex, 0) - 1) + 1; + return getValue().lastIndexOf('\n', Math.max(charIndex, 0) - 1) + 1; } // Naming things is hard. public boolean isBeforeFirstNonWhitespaceCharacterInLine(int charIndex) { - return getText() + return getValue() .substring(getLineStartBefore(charIndex), charIndex) .chars() .allMatch(Character::isWhitespace); } public String getLine(int lineIndex) { - var line = editBox.getLine(lineIndex); - return getText().substring(line.beginIndex(), line.endIndex()); + var line = editBox.getLineView(lineIndex); + return getValue().substring(line.beginIndex(), line.endIndex()); } protected int getHorizontalScroll() { @@ -392,15 +387,15 @@ protected int getHorizontalScroll() { } protected int getMaxHorizontalScroll() { - return Math.max(0, Arrays.stream(getText().split("\n")) - .mapToInt(self.getTextRenderer()::getWidth) + return Math.max(0, Arrays.stream(getValue().split("\n")) + .mapToInt(self.getFont()::width) .max() .orElse(0) + 8 - width); } protected boolean setHorizontalScroll(int horizontalScroll) { int previous = this.horizontalScroll; - this.horizontalScroll = MathHelper.clamp(horizontalScroll, 0, getMaxHorizontalScroll()); + this.horizontalScroll = Mth.clamp(horizontalScroll, 0, getMaxHorizontalScroll()); return this.horizontalScroll != previous; } @@ -414,7 +409,7 @@ protected int getMaxVerticalScroll() { protected boolean setVerticalScroll(int verticalScroll) { int previous = this.verticalScroll; - this.verticalScroll = MathHelper.clamp(verticalScroll, 0, getMaxVerticalScroll()); + this.verticalScroll = Mth.clamp(verticalScroll, 0, getMaxVerticalScroll()); return this.verticalScroll != previous; } @@ -437,11 +432,11 @@ public void setVerticalScrollEnabled(boolean enabled) { } protected void scrollToEnsureCursorVisible() { - int virtualX = getCharacterVirtualX(getCursor()); - int virtualY = getCharacterVirtualY(getCursor()); + int virtualX = getCharacterVirtualX(getCursorPosition()); + int virtualY = getCharacterVirtualY(getCursorPosition()); - setHorizontalScroll(MathHelper.clamp(horizontalScroll, virtualX - getInnerWidth(), virtualX)); - setVerticalScroll(MathHelper.clamp(verticalScroll, virtualY - getInnerHeight(), virtualY)); + setHorizontalScroll(Mth.clamp(horizontalScroll, virtualX - getInnerWidth(), virtualX)); + setVerticalScroll(Mth.clamp(verticalScroll, virtualY - getInnerHeight(), virtualY)); } public int getLineHeight() { @@ -453,7 +448,7 @@ public void setLineHeight(int lineHeight) { } public int getCharacterVirtualX(int charIndex) { - if (charIndex > getText().length()) { + if (charIndex > getValue().length()) { return 0; } String line = getLine(getLineIndex(charIndex)); @@ -463,7 +458,7 @@ public int getCharacterVirtualX(int charIndex) { indexInLine = line.length(); } - return self.getTextRenderer().getWidth(line.substring(0, indexInLine)); + return self.getFont().width(line.substring(0, indexInLine)); } public int getCharacterRealX(int charIndex) { @@ -471,7 +466,7 @@ public int getCharacterRealX(int charIndex) { } /** - * Gets the desired X position of the {@link ChatInputSuggestor} window. + * Gets the desired X position of the {@link CommandSuggestions} window. * *

This function is marked as deprecated because it does not do what * the method name says and is only here to be called by @@ -483,7 +478,7 @@ public int getCharacterRealX(int charIndex) { */ @Deprecated @Override - public int getCharacterX(int charIndex) { + public int getScreenX(int charIndex) { // Since getInnerX isn't a method in the original TextFieldWidget, // ChatInputSuggestor calls getCharacterX(0) instead. if (charIndex == 0) { @@ -495,8 +490,8 @@ public int getCharacterX(int charIndex) { } public int getCharacterVirtualY(int charIndex) { - if (charIndex > getText().length()) { - charIndex = getText().length(); + if (charIndex > getValue().length()) { + charIndex = getValue().length(); } int lineIndex = getLineIndex(charIndex); @@ -508,15 +503,15 @@ public int getCharacterRealY(int charIndex) { } private int getInnerX() { - return this.getX() + (drawsBackground() ? 4 : 0); + return this.getX() + (isBordered() ? 4 : 0); } private int getInnerY() { - return this.getY() + (drawsBackground() ? 4 : 0); + return this.getY() + (isBordered() ? 4 : 0); } private int getInnerHeight() { - return drawsBackground() ? this.height - 6 : this.height; + return isBordered() ? this.height - 6 : this.height; } private static final Logger logger = LogManager.getLogger(); @@ -527,9 +522,9 @@ public interface SyntaxHighlighter { * A syntax highlighter that performs no highlighting. */ SyntaxHighlighter NONE = text -> Arrays.stream(text.split("\n")) - .map(line -> OrderedText.styledForwardsVisitedString(line, Style.EMPTY)) + .map(line -> FormattedCharSequence.forward(line, Style.EMPTY)) .toList(); - List highlight(String text); + List highlight(String text); } } diff --git a/src/main/java/arm32x/minecraft/commandblockide/client/gui/ToolbarSeparator.java b/src/main/java/arm32x/minecraft/commandblockide/client/gui/ToolbarSeparator.java index 386fee8..192a94e 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/client/gui/ToolbarSeparator.java +++ b/src/main/java/arm32x/minecraft/commandblockide/client/gui/ToolbarSeparator.java @@ -1,38 +1,38 @@ package arm32x.minecraft.commandblockide.client.gui; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; -import net.minecraft.client.gui.widget.ClickableWidget; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Component; -public final class ToolbarSeparator extends ClickableWidget { +public final class ToolbarSeparator extends AbstractWidget { public static final int COLOR = 0x3FFFFFFF; public ToolbarSeparator() { - super(0, 0, 0, 18, Text.empty()); + super(0, 0, 0, 18, Component.empty()); } @Override - public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + public void extractWidgetRenderState(GuiGraphicsExtractor context, int mouseX, int mouseY, float delta) { context.fill(getX(), getY() + 1, getX() + 1, getY() + 1 + height, COLOR); } @Override - public SelectionType getType() { - return SelectionType.NONE; + public NarrationPriority narrationPriority() { + return NarrationPriority.NONE; } @Override - public boolean isInteractable() { + public boolean isActive() { return false; } @Override - protected MutableText getNarrationMessage() { - return Text.empty(); + protected MutableComponent createNarrationMessage() { + return Component.empty(); } @Override - public void appendClickableNarrations(NarrationMessageBuilder builder) { } + public void updateWidgetNarration(NarrationElementOutput builder) { } } diff --git a/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/CommandBlockAutoButton.java b/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/CommandBlockAutoButton.java index 2396fe6..a652a9c 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/CommandBlockAutoButton.java +++ b/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/CommandBlockAutoButton.java @@ -1,11 +1,11 @@ package arm32x.minecraft.commandblockide.client.gui.button; import arm32x.minecraft.commandblockide.client.Dirtyable; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.client.input.AbstractInput; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.input.InputWithModifiers; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; public final class CommandBlockAutoButton extends IconButton implements Dirtyable { private boolean auto = false; @@ -14,29 +14,29 @@ public final class CommandBlockAutoButton extends IconButton implements Dirtyabl public CommandBlockAutoButton(int x, int y) { super(x, y, 16, 16); - setTooltip(Tooltip.of(getTooltipText())); + setTooltip(Tooltip.create(getTooltipText())); } @Override protected Identifier getTexture() { return auto - ? Identifier.of("minecraft", "textures/item/gunpowder.png") - : Identifier.of("minecraft", "textures/item/redstone.png"); + ? Identifier.fromNamespaceAndPath("minecraft", "textures/item/gunpowder.png") + : Identifier.fromNamespaceAndPath("minecraft", "textures/item/redstone.png"); } @Override - public MutableText getNarrationMessage() { - return getNarrationMessage(getTooltipText()); + public MutableComponent createNarrationMessage() { + return wrapDefaultNarrationMessage(getTooltipText()); } - private Text getTooltipText() { + private Component getTooltipText() { return auto - ? Text.translatable("advMode.mode.autoexec.bat") - : Text.translatable("advMode.mode.redstoneTriggered"); + ? Component.translatable("advMode.mode.autoexec.bat") + : Component.translatable("advMode.mode.redstoneTriggered"); } @Override - public void onPress(AbstractInput input) { + public void onPress(InputWithModifiers input) { auto = !auto; dirty = true; updateTooltip(); @@ -55,6 +55,6 @@ public void setAuto(boolean auto) { } private void updateTooltip() { - setTooltip(Tooltip.of(getTooltipText())); + setTooltip(Tooltip.create(getTooltipText())); } } diff --git a/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/CommandBlockTrackOutputButton.java b/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/CommandBlockTrackOutputButton.java index e2d9073..340045d 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/CommandBlockTrackOutputButton.java +++ b/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/CommandBlockTrackOutputButton.java @@ -1,11 +1,11 @@ package arm32x.minecraft.commandblockide.client.gui.button; import arm32x.minecraft.commandblockide.client.Dirtyable; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.client.input.AbstractInput; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.input.InputWithModifiers; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; public final class CommandBlockTrackOutputButton extends IconButton implements Dirtyable { private boolean trackingOutput = false; @@ -20,23 +20,23 @@ public CommandBlockTrackOutputButton(int x, int y) { @Override protected Identifier getTexture() { return trackingOutput - ? Identifier.of("minecraft", "textures/item/writable_book.png") - : Identifier.of("minecraft", "textures/item/written_book.png"); + ? Identifier.fromNamespaceAndPath("minecraft", "textures/item/writable_book.png") + : Identifier.fromNamespaceAndPath("minecraft", "textures/item/written_book.png"); } @Override - public MutableText getNarrationMessage() { - return getNarrationMessage(getTooltipText()); + public MutableComponent createNarrationMessage() { + return wrapDefaultNarrationMessage(getTooltipText()); } - private Text getTooltipText() { + private Component getTooltipText() { return trackingOutput - ? Text.translatable("commandBlockIDE.lastOutput.on") - : Text.translatable("commandBlockIDE.lastOutput.off"); + ? Component.translatable("commandBlockIDE.lastOutput.on") + : Component.translatable("commandBlockIDE.lastOutput.off"); } @Override - public void onPress(AbstractInput input) { + public void onPress(InputWithModifiers input) { trackingOutput = !trackingOutput; dirty = true; updateTooltip(); @@ -46,7 +46,7 @@ public void onPress(AbstractInput input) { public boolean isDirty() { return dirty; } private void updateTooltip() { - setTooltip(Tooltip.of(getTooltipText())); + setTooltip(Tooltip.create(getTooltipText())); } public boolean isTrackingOutput() { diff --git a/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/CommandBlockTypeButton.java b/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/CommandBlockTypeButton.java index ba4889a..76655cf 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/CommandBlockTypeButton.java +++ b/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/CommandBlockTypeButton.java @@ -1,18 +1,18 @@ package arm32x.minecraft.commandblockide.client.gui.button; import arm32x.minecraft.commandblockide.client.Dirtyable; -import arm32x.minecraft.commandblockide.mixin.client.DrawContextAccessor; -import net.minecraft.block.entity.CommandBlockBlockEntity; -import net.minecraft.client.gl.RenderPipelines; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.client.input.AbstractInput; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; +import arm32x.minecraft.commandblockide.mixin.client.GuiGraphicsAccessor; +import net.minecraft.world.level.block.entity.CommandBlockEntity; +import net.minecraft.client.renderer.RenderPipelines; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.input.InputWithModifiers; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; public final class CommandBlockTypeButton extends IconButton implements Dirtyable { - private CommandBlockBlockEntity.Type type = CommandBlockBlockEntity.Type.REDSTONE; + private CommandBlockEntity.Mode type = CommandBlockEntity.Mode.REDSTONE; private boolean conditional = false; private boolean dirty = false; @@ -23,14 +23,14 @@ public CommandBlockTypeButton(int x, int y) { } @Override - public void onPress(AbstractInput input) { - if (input.hasShift()) { + public void onPress(InputWithModifiers input) { + if (input.hasShiftDown()) { conditional = !conditional; } else { switch (type) { - case REDSTONE -> type = CommandBlockBlockEntity.Type.AUTO; - case AUTO -> type = CommandBlockBlockEntity.Type.SEQUENCE; - case SEQUENCE -> type = CommandBlockBlockEntity.Type.REDSTONE; + case REDSTONE -> type = CommandBlockEntity.Mode.AUTO; + case AUTO -> type = CommandBlockEntity.Mode.SEQUENCE; + case SEQUENCE -> type = CommandBlockEntity.Mode.REDSTONE; } } dirty = true; @@ -38,17 +38,17 @@ public void onPress(AbstractInput input) { } @Override - public MutableText getNarrationMessage() { - return getNarrationMessage(getTooltipText()); + public MutableComponent createNarrationMessage() { + return wrapDefaultNarrationMessage(getTooltipText()); } - private Text getTooltipText() { + private Component getTooltipText() { StringBuilder keyBuilder = new StringBuilder("commandBlockIDE.type."); keyBuilder.append(type.name().toLowerCase()); if (conditional) { keyBuilder.append("Conditional"); } - return Text.translatable(keyBuilder.toString()); + return Component.translatable(keyBuilder.toString()); } @Override @@ -71,39 +71,39 @@ protected Identifier getTexture() { idBuilder.append("side"); } idBuilder.append(".png"); - return Identifier.of("minecraft", idBuilder.toString()); + return Identifier.fromNamespaceAndPath("minecraft", idBuilder.toString()); } @Override - public void drawIcon(DrawContext context, int mouseX, int mouseY, float delta) { + public void extractContents(GuiGraphicsExtractor context, int mouseX, int mouseY, float delta) { var texture = getTexture(); int color = active ? 0xFFFFFFFF : 0x7FFFFFFF; int shadowColor = 0x3F000000; if (active) { - context.drawTexture(RenderPipelines.GUI_TEXTURED, texture, getX() + 1, getY() + 1, 0, 0, iconWidth, iconHeight, 16, 64, shadowColor); + context.blit(RenderPipelines.GUI_TEXTURED, texture, getX() + 1, getY() + 1, 0, 0, iconWidth, iconHeight, 16, 64, shadowColor); } // The public version of drawTexturedQuad doesn't expose the color // parameter, which we need, so we have to use the private version. int x1 = getX(), x2 = x1 + 16, y1 = getY(), y2 = y1 + 16; float u1 = 0.0f, u2 = 1.0f, v1 = 0.0f, v2 = 0.25f; - ((DrawContextAccessor)context).invokeDrawTexturedQuad(RenderPipelines.GUI_TEXTURED, texture, x1, x2, y1, y2, u2, u1, v2, v1, color); + ((GuiGraphicsAccessor)context).invokeInnerBlit(RenderPipelines.GUI_TEXTURED, texture, x1, x2, y1, y2, u2, u1, v2, v1, color); } @Override public boolean isDirty() { return dirty; } private void updateTooltip() { - setTooltip(Tooltip.of(getTooltipText())); + setTooltip(Tooltip.create(getTooltipText())); } - public CommandBlockBlockEntity.Type getBlockType() { + public CommandBlockEntity.Mode getBlockType() { return type; } - public void setBlockType(CommandBlockBlockEntity.Type type) { + public void setBlockType(CommandBlockEntity.Mode type) { this.type = type; updateTooltip(); } diff --git a/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/IconButton.java b/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/IconButton.java index b1feee5..cc10c43 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/IconButton.java +++ b/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/IconButton.java @@ -1,16 +1,15 @@ package arm32x.minecraft.commandblockide.client.gui.button; -import net.minecraft.client.gl.RenderPipelines; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.cursor.StandardCursors; -import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; -import net.minecraft.client.gui.widget.PressableWidget; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.ColorHelper; - -public abstract class IconButton extends PressableWidget { +import net.minecraft.client.renderer.RenderPipelines; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.client.gui.components.AbstractButton; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; +import net.minecraft.util.ARGB; + +public abstract class IconButton extends AbstractButton { protected final int iconWidth; protected final int iconHeight; @@ -19,18 +18,18 @@ public IconButton(int x, int y, int width, int height) { } public IconButton(int x, int y, int width, int height, int iconWidth, int iconHeight) { - super(x, y, width, height, Text.empty()); + super(x, y, width, height, Component.empty()); this.iconWidth = iconWidth; this.iconHeight = iconHeight; } @Override - public final Text getMessage() { - return Text.empty(); + public final Component getMessage() { + return Component.empty(); } @Override - protected abstract MutableText getNarrationMessage(); + protected abstract MutableComponent createNarrationMessage(); protected abstract Identifier getTexture(); @@ -43,10 +42,10 @@ public boolean drawsBackground() { } @Override - public void drawIcon(DrawContext context, int mouseX, int mouseY, float delta) { + public void extractContents(GuiGraphicsExtractor context, int mouseX, int mouseY, float delta) { boolean drawsBackground = drawsBackground(); if (drawsBackground) { - this.drawButton(context); + this.extractDefaultSprite(context); } var texture = getTexture(); @@ -57,11 +56,11 @@ public void drawIcon(DrawContext context, int mouseX, int mouseY, float delta) { if (drawsBackground) { float brightness = active ? 1.0f : (float)0xA0 / 0xFF; - int color = ColorHelper.fromFloats(1.0f, brightness, brightness, brightness); - int shadowColor = ColorHelper.fromFloats(1.0f, brightness / 4, brightness / 4, brightness / 4); + int color = ARGB.colorFromFloat(1.0f, brightness, brightness, brightness); + int shadowColor = ARGB.colorFromFloat(1.0f, brightness / 4, brightness / 4, brightness / 4); - context.drawTexture(RenderPipelines.GUI_TEXTURED, texture, iconX + 1, iconY + 1, 0, 0, iconWidth, iconHeight, iconWidth, iconHeight, shadowColor); - context.drawTexture(RenderPipelines.GUI_TEXTURED, texture, iconX, iconY, 0, 0, iconWidth, iconHeight, iconWidth, iconHeight, color); + context.blit(RenderPipelines.GUI_TEXTURED, texture, iconX + 1, iconY + 1, 0, 0, iconWidth, iconHeight, iconWidth, iconHeight, shadowColor); + context.blit(RenderPipelines.GUI_TEXTURED, texture, iconX, iconY, 0, 0, iconWidth, iconHeight, iconWidth, iconHeight, color); } else { // RenderSystem.enableBlend(); // RenderSystem.defaultBlendFunc(); @@ -71,9 +70,9 @@ public void drawIcon(DrawContext context, int mouseX, int mouseY, float delta) { int shadowColor = 0x3F000000; if (active) { - context.drawTexture(RenderPipelines.GUI_TEXTURED, texture, iconX + 1, iconY + 1, 0, 0, iconWidth, iconHeight, iconWidth, iconHeight, shadowColor); + context.blit(RenderPipelines.GUI_TEXTURED, texture, iconX + 1, iconY + 1, 0, 0, iconWidth, iconHeight, iconWidth, iconHeight, shadowColor); } - context.drawTexture(RenderPipelines.GUI_TEXTURED, texture, iconX, iconY, 0, 0, iconWidth, iconHeight, iconWidth, iconHeight, color); + context.blit(RenderPipelines.GUI_TEXTURED, texture, iconX, iconY, 0, 0, iconWidth, iconHeight, iconWidth, iconHeight, color); // RenderSystem.disableDepthTest(); // RenderSystem.disableBlend(); @@ -81,7 +80,7 @@ public void drawIcon(DrawContext context, int mouseX, int mouseY, float delta) { } @Override - public void appendClickableNarrations(NarrationMessageBuilder builder) { - appendDefaultNarrations(builder); + public void updateWidgetNarration(NarrationElementOutput builder) { + defaultButtonNarrationText(builder); } } diff --git a/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/SimpleIconButton.java b/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/SimpleIconButton.java index f55bf5e..2412a23 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/SimpleIconButton.java +++ b/src/main/java/arm32x/minecraft/commandblockide/client/gui/button/SimpleIconButton.java @@ -1,11 +1,11 @@ package arm32x.minecraft.commandblockide.client.gui.button; import java.util.function.Consumer; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.client.input.AbstractInput; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.input.InputWithModifiers; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; public final class SimpleIconButton extends IconButton { private boolean drawsBackground; @@ -19,12 +19,12 @@ public SimpleIconButton(int x, int y, String iconName, Tooltip tooltip, Consumer public SimpleIconButton(int x, int y, String iconName, Tooltip tooltip, boolean drawsBackground, Consumer pressAction) { super(x, y, 20, 20, 16, 16); this.drawsBackground = drawsBackground; - this.texture = Identifier.of("commandblockide", "textures/gui/icons/" + iconName + ".png"); + this.texture = Identifier.fromNamespaceAndPath("commandblockide", "textures/gui/icons/" + iconName + ".png"); this.pressAction = pressAction; } @Override - public void onPress(AbstractInput input) { + public void onPress(InputWithModifiers input) { pressAction.accept(this); } @@ -47,7 +47,7 @@ public void setDrawsBackground(boolean drawsBackground) { } @Override - protected MutableText getNarrationMessage() { - return getNarrationMessage(Text.empty()); + protected MutableComponent createNarrationMessage() { + return wrapDefaultNarrationMessage(Component.empty()); } } diff --git a/src/main/java/arm32x/minecraft/commandblockide/client/gui/editor/CommandBlockEditor.java b/src/main/java/arm32x/minecraft/commandblockide/client/gui/editor/CommandBlockEditor.java index 17ffe3e..a984108 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/client/gui/editor/CommandBlockEditor.java +++ b/src/main/java/arm32x/minecraft/commandblockide/client/gui/editor/CommandBlockEditor.java @@ -8,22 +8,22 @@ import arm32x.minecraft.commandblockide.client.update.DataCommandUpdateRequester; import java.util.Objects; import java.util.stream.Stream; -import net.minecraft.block.entity.CommandBlockBlockEntity; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.TextFieldWidget; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.network.packet.c2s.play.UpdateCommandBlockC2SPacket; -import net.minecraft.text.Text; -import net.minecraft.world.CommandBlockExecutor; +import net.minecraft.world.level.block.entity.CommandBlockEntity; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.protocol.game.ServerboundSetCommandBlockPacket; +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.BaseCommandBlock; public final class CommandBlockEditor extends CommandEditor { - private final CommandBlockBlockEntity blockEntity; + private final CommandBlockEntity blockEntity; - private final TextFieldWidget lastOutputField; + private final EditBox lastOutputField; private final CommandBlockTypeButton typeButton; private final CommandBlockAutoButton autoButton; @@ -31,30 +31,30 @@ public final class CommandBlockEditor extends CommandEditor { private boolean commandFieldDirty = false; - public CommandBlockEditor(Screen screen, TextRenderer textRenderer, int x, int y, int width, int height, CommandBlockBlockEntity blockEntity, int index) { + public CommandBlockEditor(Screen screen, Font textRenderer, int x, int y, int width, int height, CommandBlockEntity blockEntity, int index) { super(screen, textRenderer, x, y, width, height, 40, 20, index); this.blockEntity = blockEntity; commandField.setMaxLength(32500); - lastOutputField = new TextFieldWidget( + lastOutputField = new EditBox( textRenderer, commandField.getX(), commandField.getY(), commandField.getWidth(), commandField.getHeight(), - Text.translatable("advMode.previousOutput") - .append(Text.translatable("commandBlockIDE.narrator.editorIndex", index + 1)) + Component.translatable("advMode.previousOutput") + .append(Component.translatable("commandBlockIDE.narrator.editorIndex", index + 1)) ); lastOutputField.setEditable(false); lastOutputField.setMaxLength(32500); - lastOutputField.setText(Text.translatable("commandBlockIDE.unloaded").getString()); + lastOutputField.setValue(Component.translatable("commandBlockIDE.unloaded").getString()); lastOutputField.visible = false; typeButton = addDrawableChild(new CommandBlockTypeButton(x + 20, y)); - typeButton.setBlockType(blockEntity.getCommandBlockType()); + typeButton.setBlockType(blockEntity.getMode()); typeButton.active = false; autoButton = addDrawableChild(new CommandBlockAutoButton(x + 40, y)); - autoButton.setAuto(typeButton.getBlockType() == CommandBlockBlockEntity.Type.SEQUENCE); + autoButton.setAuto(typeButton.getBlockType() == CommandBlockEntity.Mode.SEQUENCE); autoButton.active = false; trackOutputButton = addDrawableChild(new CommandBlockTrackOutputButton(x + width - 16, y)); @@ -62,11 +62,11 @@ public CommandBlockEditor(Screen screen, TextRenderer textRenderer, int x, int y trackOutputButton.active = false; } - public void save(ClientPlayNetworkHandler networkHandler) { + public void save(ClientPacketListener networkHandler) { if (isLoaded() && isDirty()) { - CommandBlockExecutor executor = blockEntity.getCommandExecutor(); - networkHandler.sendPacket(new UpdateCommandBlockC2SPacket( - blockEntity.getPos(), + BaseCommandBlock executor = blockEntity.getCommandBlock(); + networkHandler.send(new ServerboundSetCommandBlockPacket( + blockEntity.getBlockPos(), getSingleLineCommand(), typeButton.getBlockType(), trackOutputButton.isTrackingOutput(), @@ -82,66 +82,66 @@ public void save(ClientPlayNetworkHandler networkHandler) { } private void saveMultilineCommand() { - MinecraftClient client = MinecraftClient.getInstance(); - String world = client.isInSingleplayer() - ? Objects.requireNonNull(client.getServer()).getSaveProperties().getLevelName() - : Objects.requireNonNull(client.getCurrentServerEntry()).name; + Minecraft client = Minecraft.getInstance(); + String world = client.isLocalServer() + ? Objects.requireNonNull(client.getSingleplayerServer()).getWorldData().getLevelName() + : Objects.requireNonNull(client.getCurrentServer()).name; - MultilineCommandStorage.getInstance().add(commandField.getText(), getSingleLineCommand(), client.isInSingleplayer(), world, blockEntity.getPos()); + MultilineCommandStorage.getInstance().add(commandField.getValue(), getSingleLineCommand(), client.isLocalServer(), world, blockEntity.getBlockPos()); } public void update() { - CommandBlockExecutor executor = blockEntity.getCommandExecutor(); - MinecraftClient client = MinecraftClient.getInstance(); - commandField.setText(MultilineCommandStorage.getInstance().getRobust( + BaseCommandBlock executor = blockEntity.getCommandBlock(); + Minecraft client = Minecraft.getInstance(); + commandField.setValue(MultilineCommandStorage.getInstance().getRobust( executor.getCommand(), processor, - client.isInSingleplayer(), - client.isInSingleplayer() - ? Objects.requireNonNull(client.getServer()).getSaveProperties().getLevelName() - : Objects.requireNonNull(client.getCurrentServerEntry()).name, - blockEntity.getPos() + client.isLocalServer(), + client.isLocalServer() + ? Objects.requireNonNull(client.getSingleplayerServer()).getWorldData().getLevelName() + : Objects.requireNonNull(client.getCurrentServer()).name, + blockEntity.getBlockPos() )); - typeButton.setBlockType(blockEntity.getCommandBlockType()); - typeButton.setConditional(blockEntity.isConditionalCommandBlock()); - autoButton.setAuto(blockEntity.isAuto()); - trackOutputButton.setTrackingOutput(executor.isTrackingOutput()); + typeButton.setBlockType(blockEntity.getMode()); + typeButton.setConditional(blockEntity.isConditional()); + autoButton.setAuto(blockEntity.isAutomatic()); + trackOutputButton.setTrackingOutput(executor.isTrackOutput()); String lastOutput = executor.getLastOutput().getString(); if (lastOutput.isEmpty()) { - lastOutput = Text.translatable("commandBlockIDE.lastOutput.none").getString(); + lastOutput = Component.translatable("commandBlockIDE.lastOutput.none").getString(); } - lastOutputField.setText(lastOutput); + lastOutputField.setValue(lastOutput); - suggestor.setWindowActive(commandField.isActive()); - suggestor.refresh(); + suggestor.setAllowSuggestions(commandField.canConsumeInput()); + suggestor.updateCommandInfo(); commandFieldDirty = false; setLoaded(true); } - public void requestUpdate(ClientPlayerEntity player) { + public void requestUpdate(LocalPlayer player) { DataCommandUpdateRequester.getInstance().requestUpdate(player, blockEntity); } @Override public void commandChanged(String newCommand) { - if (!newCommand.equals(blockEntity.getCommandExecutor().getCommand())) { + if (!newCommand.equals(blockEntity.getCommandBlock().getCommand())) { commandFieldDirty = true; } super.commandChanged(newCommand); } @Override - protected void renderCommandField(DrawContext context, int mouseX, int mouseY, float delta) { + protected void extractCommandField(GuiGraphicsExtractor context, int mouseX, int mouseY, float delta) { if (trackOutputButton.isMouseOver(mouseX, mouseY)) { commandField.visible = false; lastOutputField.visible = true; - lastOutputField.render(context, mouseX, mouseY, delta); + lastOutputField.extractRenderState(context, mouseX, mouseY, delta); } else { commandField.visible = true; lastOutputField.visible = false; - commandField.render(context, mouseX, mouseY, delta); + commandField.extractRenderState(context, mouseX, mouseY, delta); } } diff --git a/src/main/java/arm32x/minecraft/commandblockide/client/gui/editor/CommandEditor.java b/src/main/java/arm32x/minecraft/commandblockide/client/gui/editor/CommandEditor.java index 7086cd6..4a48f8b 100644 --- a/src/main/java/arm32x/minecraft/commandblockide/client/gui/editor/CommandEditor.java +++ b/src/main/java/arm32x/minecraft/commandblockide/client/gui/editor/CommandEditor.java @@ -6,7 +6,7 @@ import arm32x.minecraft.commandblockide.client.processor.CommandProcessor; import arm32x.minecraft.commandblockide.client.processor.MultilineCommandProcessor; import arm32x.minecraft.commandblockide.client.processor.StringMapping; -import arm32x.minecraft.commandblockide.mixin.client.ChatInputSuggestorAccessor; +import arm32x.minecraft.commandblockide.mixin.client.CommandSuggestionsAccessor; import arm32x.minecraft.commandblockide.mixinextensions.client.ChatInputSuggestorExtension; import com.mojang.brigadier.ParseResults; import com.mojang.brigadier.context.ParsedArgument; @@ -18,22 +18,22 @@ import java.util.stream.Stream; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.Click; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.ChatInputSuggestor; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; -import net.minecraft.client.gui.screen.narration.NarrationPart; -import net.minecraft.client.input.CharInput; -import net.minecraft.client.input.KeyInput; -import net.minecraft.command.CommandSource; -import net.minecraft.text.MutableText; -import net.minecraft.text.OrderedText; -import net.minecraft.text.Style; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.input.MouseButtonEvent; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.components.CommandSuggestions; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.client.gui.narration.NarratedElementType; +import net.minecraft.client.input.CharacterEvent; +import net.minecraft.client.input.KeyEvent; +import net.minecraft.client.multiplayer.ClientSuggestionProvider; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.util.FormattedCharSequence; +import net.minecraft.network.chat.Style; +import net.minecraft.network.chat.Component; +import net.minecraft.ChatFormatting; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; @@ -49,10 +49,10 @@ public abstract class CommandEditor extends Container implements Dirtyable { public final int index; public boolean lineNumberHighlighted = false; - protected final TextRenderer textRenderer; + protected final Font textRenderer; protected final MultilineTextFieldWidget commandField; - protected final ChatInputSuggestor suggestor; + protected final CommandSuggestions suggestor; protected final CommandProcessor processor = MultilineCommandProcessor.getInstance(); private boolean suggestorActive = false; @@ -62,7 +62,7 @@ public abstract class CommandEditor extends Container implements Dirtyable { protected @Nullable IntConsumer heightChangedListener = null; @SuppressWarnings("ConstantConditions") - public CommandEditor(Screen screen, TextRenderer textRenderer, int x, int y, int width, int height, int leftPadding, int rightPadding, int index) { + public CommandEditor(Screen screen, Font textRenderer, int x, int y, int width, int height, int leftPadding, int rightPadding, int index) { this.x = x; this.y = y; this.width = width; @@ -76,27 +76,27 @@ public CommandEditor(Screen screen, TextRenderer textRenderer, int x, int y, int textRenderer, x + leftPadding + 20, y, width - leftPadding - rightPadding - 20, height, - Text.translatable("advMode.command") - .append(Text.translatable("commandBlockIDE.narrator.editorIndex", index + 1)) + Component.translatable("advMode.command") + .append(Component.translatable("commandBlockIDE.narrator.editorIndex", index + 1)) ) { @Override - protected MutableText getNarrationMessage() { - return super.getNarrationMessage().append(suggestor.getNarration()); + protected MutableComponent createNarrationMessage() { + return super.createNarrationMessage().append(suggestor.getNarrationMessage()); } }); commandField.setEditable(false); commandField.setMaxLength(Integer.MAX_VALUE); - suggestor = new ChatInputSuggestor(MinecraftClient.getInstance(), screen, commandField, textRenderer, true, true, 0, 16, false, Integer.MIN_VALUE); + suggestor = new CommandSuggestions(Minecraft.getInstance(), screen, commandField, textRenderer, true, true, 0, 16, false, Integer.MIN_VALUE); ((ChatInputSuggestorExtension) suggestor).ide$setCommandProcessor(processor); - suggestor.refresh(); + suggestor.updateCommandInfo(); - commandField.setChangedListener(this::commandChanged); - commandField.setCursorChangeListener(suggestor::refresh); + commandField.setResponder(this::commandChanged); + commandField.setCursorChangeListener(suggestor::updateCommandInfo); commandField.setSyntaxHighlighter((text) -> { - var parse = ((ChatInputSuggestorAccessor) suggestor).getParse(); + var parse = ((CommandSuggestionsAccessor) suggestor).getCurrentParse(); if (parse != null) { - return highlight(parse, text, processor.processCommand(text).getRight()); + return highlight(parse, text, processor.processCommand(text).getB()); } else { // The command hasn't been parsed yet, so we show it without // highlighting. I haven't ever seen this in game, though. @@ -106,12 +106,12 @@ protected MutableText getNarrationMessage() { } public void commandChanged(String newCommand) { - suggestor.refresh(); + suggestor.updateCommandInfo(); setHeight(commandField.getLineCount() * commandField.getLineHeight() + 4); } @Override - public boolean keyPressed(KeyInput input) { + public boolean keyPressed(KeyEvent input) { if (handleSpecialKey(input)) { return true; } else if (isSuggestorActive() && suggestor.keyPressed(input)) { @@ -126,21 +126,21 @@ public boolean keyPressed(KeyInput input) { } } - private boolean handleSpecialKey(KeyInput input) { + private boolean handleSpecialKey(KeyEvent input) { if ( input.key() == GLFW.GLFW_KEY_TAB && !isSuggestorActive() - && !commandField.isBeforeFirstNonWhitespaceCharacterInLine(commandField.getCursor()) + && !commandField.isBeforeFirstNonWhitespaceCharacterInLine(commandField.getCursorPosition()) ) { setSuggestorActive(true); - suggestor.refresh(); + suggestor.updateCommandInfo(); // Immediately trigger completion without using Mixin by // simulating a key press. The scancode and modifiers arguments // are never used. - return suggestor.keyPressed(new KeyInput(GLFW.GLFW_KEY_TAB, -1, 0)); - } else if (input.key() == GLFW.GLFW_KEY_SPACE && input.hasCtrl()) { + return suggestor.keyPressed(new KeyEvent(GLFW.GLFW_KEY_TAB, -1, 0)); + } else if (input.key() == GLFW.GLFW_KEY_SPACE && input.hasControlDown()) { setSuggestorActive(true); - suggestor.show(true); + suggestor.showSuggestions(true); return true; } // The Escape key is handled in CommandIDEScreen, not here. @@ -148,12 +148,12 @@ private boolean handleSpecialKey(KeyInput input) { } @Override - public boolean charTyped(CharInput input) { + public boolean charTyped(CharacterEvent input) { if (super.charTyped(input)) { // The if statement ensures that only valid characters will trigger // the suggestions box. setSuggestorActive(true); - suggestor.refresh(); + suggestor.updateCommandInfo(); return true; } else { return false; @@ -161,10 +161,10 @@ public boolean charTyped(CharInput input) { } @Override - public boolean mouseClicked(Click click, boolean doubled) { + public boolean mouseClicked(MouseButtonEvent click, boolean doubled) { boolean result = suggestor.mouseClicked(click) || super.mouseClicked(click, doubled); - suggestor.setWindowActive(false); + suggestor.setAllowSuggestions(false); return result; } @@ -178,40 +178,40 @@ public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmou public void setFocused(boolean focused) { setFocused(commandField); commandField.setFocused(focused); - suggestor.setWindowActive(false); + suggestor.setAllowSuggestions(false); } @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { - renderLineNumber(context); + public void extractRenderState(GuiGraphicsExtractor context, int mouseX, int mouseY, float delta) { + extractLineNumber(context); if (isLoaded()) { - renderCommandField(context, mouseX, mouseY, delta); + extractCommandField(context, mouseX, mouseY, delta); } else { - context.drawText(textRenderer, Text.translatable("commandBlockIDE.unloaded"), commandField.getX(), y + 5, 0x7FFFFFFF, false); + context.text(textRenderer, Component.translatable("commandBlockIDE.unloaded"), commandField.getX(), y + 5, 0x7FFFFFFF); } - super.render(context, mouseX, mouseY, delta); + super.extractRenderState(context, mouseX, mouseY, delta); } - protected void renderLineNumber(DrawContext context) { + protected void extractLineNumber(GuiGraphicsExtractor context) { String lineNumber = String.valueOf(index + 1); // Manually draw shadow because the existing functions don’t let you set the color. - context.drawText(textRenderer, lineNumber, x + 17 - textRenderer.getWidth(lineNumber), y + 5, 0x3F000000, false); - context.drawText(textRenderer, lineNumber, x + 16 - textRenderer.getWidth(lineNumber), y + 4, lineNumberHighlighted ? 0xFFFFFFFF : 0x7FFFFFFF, false); + context.text(textRenderer, lineNumber, x + 17 - textRenderer.width(lineNumber), y + 5, 0x3F000000); + context.text(textRenderer, lineNumber, x + 16 - textRenderer.width(lineNumber), y + 4, lineNumberHighlighted ? 0xFFFFFFFF : 0x7FFFFFFF); } - protected void renderCommandField(DrawContext context, int mouseX, int mouseY, float delta) { + protected void extractCommandField(GuiGraphicsExtractor context, int mouseX, int mouseY, float delta) { commandField.visible = true; - commandField.render(context, mouseX, mouseY, delta); + commandField.extractRenderState(context, mouseX, mouseY, delta); } - public void renderSuggestions(DrawContext context, int mouseX, int mouseY) { - if (commandField.isActive()) { - suggestor.render(context, mouseX, mouseY); + public void extractSuggestions(GuiGraphicsExtractor context, int mouseX, int mouseY) { + if (commandField.canConsumeInput()) { + suggestor.extractRenderState(context, mouseX, mouseY); } } public String getSingleLineCommand() { - return processor.processCommand(commandField.getText()).getLeft(); + return processor.processCommand(commandField.getValue()).getA(); } public boolean isLoaded() { @@ -236,7 +236,7 @@ public void setY(int y) { this.y = y; commandField.setY(y); - suggestor.refresh(); + suggestor.updateCommandInfo(); } @@ -249,7 +249,7 @@ public void setWidth(int width) { commandField.setWidth(width - leftPadding - rightPadding - 20); - suggestor.refresh(); + suggestor.updateCommandInfo(); } public int getHeight() { @@ -262,7 +262,7 @@ public void setHeight(int height) { commandField.setHeight(height); - suggestor.refresh(); + suggestor.updateCommandInfo(); if (changed) { onHeightChange(height); @@ -274,7 +274,7 @@ public boolean isSuggestorActive() { } public void setSuggestorActive(boolean suggestorActive) { - suggestor.setWindowActive(suggestorActive); + suggestor.setAllowSuggestions(suggestorActive); this.suggestorActive = suggestorActive; } @@ -289,11 +289,11 @@ public void setHeightChangedListener(@Nullable IntConsumer listener) { } @Override - public void appendNarrations(NarrationMessageBuilder builder) { - builder.put(NarrationPart.TITLE, Text.translatable("narration.edit_box", commandField.getText())); + public void updateNarration(NarrationElementOutput builder) { + builder.add(NarratedElementType.TITLE, Component.translatable("narration.edit_box", commandField.getValue())); } - protected static List highlight(ParseResults parse, String text, StringMapping mapping) { + protected static List highlight(ParseResults parse, String text, StringMapping mapping) { // The ranges of text in the single-line command containing each // argument that should be highlighted. List ranges = parse @@ -309,7 +309,7 @@ protected static List highlight(ParseResults parse, // or after this index is a parse error. int mappedParseStopIndex = mapping.mapIndexOrAfter(parse.getReader().getCursor()); - List highlightedLines = new ArrayList<>(); + List highlightedLines = new ArrayList<>(); int startIndex = 0; while (startIndex <= text.length()) { @@ -366,14 +366,14 @@ protected static List highlight(ParseResults parse, } private static final List