diff --git a/common/src/main/java/dev/boxadactle/mcshare/MCShare.java b/common/src/main/java/dev/boxadactle/mcshare/MCShare.java index f865948..9bfce59 100644 --- a/common/src/main/java/dev/boxadactle/mcshare/MCShare.java +++ b/common/src/main/java/dev/boxadactle/mcshare/MCShare.java @@ -2,6 +2,14 @@ import dev.boxadactle.boxlib.util.ClientUtils; import dev.boxadactle.boxlib.util.ModLogger; +import dev.boxadactle.boxlib.util.function.EmptyMethod; +import dev.boxadactle.mcshare.gui.importing.WorldImportScreen; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.tabs.GridLayoutTab; +import net.minecraft.client.gui.components.tabs.Tab; +import net.minecraft.client.gui.layouts.GridLayout; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; import java.nio.file.Path; @@ -27,4 +35,23 @@ public static void init() { public static Path getWorldFolder() { return Path.of(ClientUtils.getClient().gameDirectory.getAbsolutePath(), "saves"); } + + public static class ImportTab extends GridLayoutTab { + + Screen parent; + + public ImportTab(Screen parent) { + super(Component.translatable("screen.mcshare.importworld")); + + this.parent = parent; + + GridLayout.RowHelper gridlayout$rowhelper = this.layout.rowSpacing(8).createRowHelper(1); + + gridlayout$rowhelper.addChild(Button.builder(Component.translatable("button.mcshare.import"), this::openImportScreen).width(210).build()); + } + + private void openImportScreen(Button b) { + ClientUtils.setScreen(new WorldImportScreen(parent)); + } + } } diff --git a/common/src/main/java/dev/boxadactle/mcshare/gui/exporting/ExportingScreen.java b/common/src/main/java/dev/boxadactle/mcshare/gui/exporting/ExportingScreen.java index 531c6e1..67bb83b 100644 --- a/common/src/main/java/dev/boxadactle/mcshare/gui/exporting/ExportingScreen.java +++ b/common/src/main/java/dev/boxadactle/mcshare/gui/exporting/ExportingScreen.java @@ -16,8 +16,8 @@ public class ExportingScreen extends Screen { Screen parent; - boolean isFinished = false; - boolean isError = false; + boolean isFinished; + boolean isError; String error; Button finish; @@ -33,27 +33,6 @@ protected ExportingScreen(Screen parent, LevelStorageSource.LevelStorageAccess a path = filePath; } - @Override - protected void init() { - int number = BConfigHelper.buttonWidth(BConfigHelper.ButtonType.SMALL); - finish = addRenderableWidget(Button.builder(GuiUtils.DONE, b -> onClose()) - .bounds(width / 2 - number - 1, height / 2 + 40, number, 20) - .build() - ); - - openFile = addRenderableWidget(Button.builder(Component.translatable("button.mcshare.open"), this::openFile) - .bounds(width / 2 + 1, height / 2 + 40, number, 20) - .build() - ); - } - - @Override - public void tick() { - finish.visible = isFinished; - openFile.visible = isFinished; - openFile.active = !isError; - } - @Override public void render(GuiGraphics guiGraphics, int i, int j, float f) { renderBackground(guiGraphics); @@ -71,18 +50,35 @@ private void openFile(Button b) { Util.getPlatform().openFile(path.getParent().toFile()); } - public void setFinished(boolean finished) { - isFinished = finished; + public void setFinished() { + isFinished = true; + + activateButtons(true); } - public void setErrored(boolean errored, String error) { - isError = errored; + public void setErrored(String error) { + isError = true; this.error = error; + + activateButtons(false); + } + + private void activateButtons(boolean bl) { + int number = BConfigHelper.buttonWidth(BConfigHelper.ButtonType.SMALL); + addRenderableWidget(Button.builder(GuiUtils.DONE, b -> onClose()) + .bounds(width / 2 - number - 1, height / 2 + 40, number, 20) + .build() + ); + + addRenderableWidget(Button.builder(Component.translatable("button.mcshare.open"), this::openFile) + .bounds(width / 2 + 1, height / 2 + 40, number, 20) + .build() + ).active = bl; } @Override public boolean shouldCloseOnEsc() { - return isFinished; + return isFinished || isError; } @Override diff --git a/common/src/main/java/dev/boxadactle/mcshare/gui/importing/ImportingScreen.java b/common/src/main/java/dev/boxadactle/mcshare/gui/importing/ImportingScreen.java index c55ea5b..64cf563 100644 --- a/common/src/main/java/dev/boxadactle/mcshare/gui/importing/ImportingScreen.java +++ b/common/src/main/java/dev/boxadactle/mcshare/gui/importing/ImportingScreen.java @@ -3,11 +3,14 @@ import dev.boxadactle.boxlib.config.gui.BConfigHelper; import dev.boxadactle.boxlib.util.GuiUtils; import dev.boxadactle.mcshare.MCShare; -import dev.boxadactle.mcshare.mixin.ParentAccessor; +import dev.boxadactle.mcshare.mixin.CreateWorldParentAccessor; +import dev.boxadactle.mcshare.mixin.SelectWorldParentAccessor; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.GenericDirtMessageScreen; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.TitleScreen; +import net.minecraft.client.gui.screens.worldselection.CreateWorldScreen; import net.minecraft.client.gui.screens.worldselection.SelectWorldScreen; import net.minecraft.network.chat.Component; @@ -20,9 +23,6 @@ public class ImportingScreen extends Screen { String error; - Button finish; - Button playWorld; - String worldName; protected ImportingScreen(Screen parent, String name) { @@ -32,28 +32,6 @@ protected ImportingScreen(Screen parent, String name) { worldName = name; } - @Override - protected void init() { - int number = BConfigHelper.buttonWidth(BConfigHelper.ButtonType.SMALL); - - finish = addRenderableWidget(Button.builder(GuiUtils.DONE, b -> onClose()) - .bounds(width / 2 - number - 1, height - 40, number, 20) - .build() - ); - - playWorld = addRenderableWidget(Button.builder(Component.translatable("button.mcshare.play"), this::playWorld) - .bounds(width / 2 + 1, height - 40, number, 20) - .build() - ); - } - - @Override - public void tick() { - finish.visible = isFinished; - playWorld.visible = isFinished; - playWorld.active = !isError; - } - @Override public void render(GuiGraphics guiGraphics, int i, int j, float f) { renderBackground(guiGraphics); @@ -73,23 +51,49 @@ private void playWorld(Button button) { this.minecraft.createWorldOpenFlows().loadLevel(this, worldName.replace(MCShare.WORLD_EXTENSION, "")); } - public void setFinished(boolean finished) { - isFinished = finished; + public void setFinished() { + isFinished = true; + + activateButtons(true); } - public void setErrored(boolean error, String errorMessage) { - isError = error; + public void setErrored(String errorMessage) { + isError = true; this.error = errorMessage; + + activateButtons(false); + } + + private void activateButtons(boolean bl) { + int number = BConfigHelper.buttonWidth(BConfigHelper.ButtonType.SMALL); + + addRenderableWidget(Button.builder(GuiUtils.DONE, b -> onClose()) + .bounds(width / 2 - number - 1, height - 40, number, 20) + .build() + ); + + addRenderableWidget(Button.builder(Component.translatable("button.mcshare.play"), this::playWorld) + .bounds(width / 2 + 1, height - 40, number, 20) + .build() + ).active = bl; } @Override public boolean shouldCloseOnEsc() { - return isFinished; + return isFinished || isError; } @Override public void onClose() { - minecraft.setScreen(new SelectWorldScreen(((ParentAccessor)parent).getParent())); + if (parent instanceof SelectWorldScreen) { + minecraft.setScreen(new SelectWorldScreen(((SelectWorldParentAccessor) parent).getParent())); + } else if (parent instanceof CreateWorldScreen) { + minecraft.setScreen(new SelectWorldScreen(((CreateWorldParentAccessor) parent).getParent())); + } + else { + MCShare.LOGGER.error("Parent was not an instance of {} or {}", SelectWorldScreen.class, CreateWorldScreen.class); + minecraft.setScreen(new TitleScreen()); + } } } \ No newline at end of file diff --git a/common/src/main/java/dev/boxadactle/mcshare/mixin/CreateWorldParentAccessor.java b/common/src/main/java/dev/boxadactle/mcshare/mixin/CreateWorldParentAccessor.java new file mode 100644 index 0000000..3e72346 --- /dev/null +++ b/common/src/main/java/dev/boxadactle/mcshare/mixin/CreateWorldParentAccessor.java @@ -0,0 +1,14 @@ +package dev.boxadactle.mcshare.mixin; + +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.worldselection.CreateWorldScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(CreateWorldScreen.class) +public interface CreateWorldParentAccessor { + + @Accessor("lastScreen") + Screen getParent(); + +} diff --git a/common/src/main/java/dev/boxadactle/mcshare/mixin/CreateWorldScreenMixin.java b/common/src/main/java/dev/boxadactle/mcshare/mixin/CreateWorldScreenMixin.java new file mode 100644 index 0000000..366f2b4 --- /dev/null +++ b/common/src/main/java/dev/boxadactle/mcshare/mixin/CreateWorldScreenMixin.java @@ -0,0 +1,37 @@ +package dev.boxadactle.mcshare.mixin; + +import dev.boxadactle.mcshare.MCShare; +import net.minecraft.client.gui.components.tabs.Tab; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +import java.util.Arrays; + +@Mixin(net.minecraft.client.gui.screens.worldselection.CreateWorldScreen.class) +public abstract class CreateWorldScreenMixin extends Screen { + + protected CreateWorldScreenMixin(Component component) { + super(component); + } + + // some IDEs will show this return value as an error + @ModifyArg( + method = "init", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/gui/components/tabs/TabNavigationBar$Builder;addTabs([Lnet/minecraft/client/gui/components/tabs/Tab;)Lnet/minecraft/client/gui/components/tabs/TabNavigationBar$Builder;", + ordinal = 0 + ) + ) + private Tab[] addImportTab(Tab[] args) { + Tab[] cloned = Arrays.copyOf(args, args.length + 1); + + cloned[cloned.length - 1] = new MCShare.ImportTab(this); + + return cloned; + } + +} diff --git a/common/src/main/java/dev/boxadactle/mcshare/mixin/ParentAccessor.java b/common/src/main/java/dev/boxadactle/mcshare/mixin/SelectWorldParentAccessor.java similarity index 88% rename from common/src/main/java/dev/boxadactle/mcshare/mixin/ParentAccessor.java rename to common/src/main/java/dev/boxadactle/mcshare/mixin/SelectWorldParentAccessor.java index 2cd2d13..cb45191 100644 --- a/common/src/main/java/dev/boxadactle/mcshare/mixin/ParentAccessor.java +++ b/common/src/main/java/dev/boxadactle/mcshare/mixin/SelectWorldParentAccessor.java @@ -6,7 +6,7 @@ import org.spongepowered.asm.mixin.gen.Accessor; @Mixin(SelectWorldScreen.class) -public interface ParentAccessor { +public interface SelectWorldParentAccessor { @Accessor("lastScreen") Screen getParent(); diff --git a/common/src/main/java/dev/boxadactle/mcshare/util/WorldExporter.java b/common/src/main/java/dev/boxadactle/mcshare/util/WorldExporter.java index 8c5b805..bc70c72 100644 --- a/common/src/main/java/dev/boxadactle/mcshare/util/WorldExporter.java +++ b/common/src/main/java/dev/boxadactle/mcshare/util/WorldExporter.java @@ -54,12 +54,19 @@ public static void startExport(ExportOptions options) { zipFile.addFolder(options.worldPath.toFile(), parameters); MCShare.LOGGER.info("Finished!"); - options.screen.setFinished(true); + options.screen.setFinished(); } catch (Exception e) { - MCShare.LOGGER.error("Error occurred when exporting!"); - MCShare.LOGGER.printStackTrace(e); + if (e.getMessage().toLowerCase().contains("locked a portion of the file")) { + MCShare.LOGGER.warn("File has been locked, either you are on windows or this is a bug!"); + options.screen.setFinished(); + } - options.screen.setErrored(true, e.getMessage()); + else { + MCShare.LOGGER.error("Error occurred when exporting!"); + MCShare.LOGGER.printStackTrace(e); + + options.screen.setErrored(e.getMessage()); + } } } diff --git a/common/src/main/java/dev/boxadactle/mcshare/util/WorldImporter.java b/common/src/main/java/dev/boxadactle/mcshare/util/WorldImporter.java index 37dbd14..5700131 100644 --- a/common/src/main/java/dev/boxadactle/mcshare/util/WorldImporter.java +++ b/common/src/main/java/dev/boxadactle/mcshare/util/WorldImporter.java @@ -45,12 +45,14 @@ public static void startImport(ImportOptions options) { file.extractAll(p.toString()); - options.screen.setFinished(true); + options.screen.setFinished(); + + MCShare.LOGGER.info("Finished!"); } catch (Exception e) { - MCShare.LOGGER.error("An error occured!"); + MCShare.LOGGER.error("An error occured while importing!"); MCShare.LOGGER.printStackTrace(e); - options.screen.setErrored(true, e.getMessage()); + options.screen.setErrored(e.getMessage()); } } diff --git a/common/src/main/resources/mcshare-common.mixins.json b/common/src/main/resources/mcshare-common.mixins.json index cafb367..3091f6f 100644 --- a/common/src/main/resources/mcshare-common.mixins.json +++ b/common/src/main/resources/mcshare-common.mixins.json @@ -4,8 +4,10 @@ "package": "dev.boxadactle.mcshare.mixin", "compatibilityLevel": "JAVA_17", "client": [ + "CreateWorldParentAccessor", + "CreateWorldScreenMixin", "EditWorldScreenMixin", - "ParentAccessor", + "SelectWorldParentAccessor", "SelectWorldScreenMixin" ], "injectors": {