diff --git a/src/main/java/com/replaymod/core/ReplayMod.java b/src/main/java/com/replaymod/core/ReplayMod.java index 85f5f0fa..faa6e476 100644 --- a/src/main/java/com/replaymod/core/ReplayMod.java +++ b/src/main/java/com/replaymod/core/ReplayMod.java @@ -138,6 +138,7 @@ public class ReplayMod implements public static final Identifier TEXTURE = new Identifier("replaymod", "replay_gui.png"); public static final int TEXTURE_SIZE = 256; + public static final Identifier LOGO_FAVICON = new Identifier("replaymod", "favicon_logo.png"); private static final MinecraftClient mc = MCVer.getMinecraft(); diff --git a/src/main/java/com/replaymod/core/gui/GuiReplayButton.java b/src/main/java/com/replaymod/core/gui/GuiReplayButton.java new file mode 100644 index 00000000..9bd3476f --- /dev/null +++ b/src/main/java/com/replaymod/core/gui/GuiReplayButton.java @@ -0,0 +1,17 @@ +package com.replaymod.core.gui; + +import com.replaymod.core.ReplayMod; +import de.johni0702.minecraft.gui.GuiRenderer; +import de.johni0702.minecraft.gui.RenderInfo; +import de.johni0702.minecraft.gui.element.GuiButton; +import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension; + +public class GuiReplayButton extends GuiButton { + @Override + public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) { + super.draw(renderer, size, renderInfo); + + renderer.bindTexture(ReplayMod.LOGO_FAVICON); + renderer.drawTexturedRect(3, 3, 0, 0, size.getWidth() - 6, size.getHeight() - 6, 1, 1, 1, 1); + } +} diff --git a/src/main/java/com/replaymod/recording/ServerInfoExt.java b/src/main/java/com/replaymod/recording/ServerInfoExt.java new file mode 100644 index 00000000..a0f26756 --- /dev/null +++ b/src/main/java/com/replaymod/recording/ServerInfoExt.java @@ -0,0 +1,17 @@ +package com.replaymod.recording; + +import net.minecraft.client.network.ServerInfo; + +/** Extension interface for {@link net.minecraft.client.network.ServerInfo}. */ +public interface ServerInfoExt { + + static ServerInfoExt from(ServerInfo base) { + return (ServerInfoExt) base; + } + + /** Per-server optional overwrite for {@link Setting#AUTO_START_RECORDING}. */ + Boolean getAutoRecording(); + + /** Per-server optional overwrite for {@link Setting#AUTO_START_RECORDING}. */ + void setAutoRecording(Boolean autoRecording); +} diff --git a/src/main/java/com/replaymod/recording/gui/GuiRecordingControls.java b/src/main/java/com/replaymod/recording/gui/GuiRecordingControls.java index c34c21e2..cc36488f 100644 --- a/src/main/java/com/replaymod/recording/gui/GuiRecordingControls.java +++ b/src/main/java/com/replaymod/recording/gui/GuiRecordingControls.java @@ -69,11 +69,11 @@ public class GuiRecordingControls extends EventRegistrations { updateState(); }).setSize(98, 20); - public GuiRecordingControls(ReplayMod core, PacketListener packetListener) { + public GuiRecordingControls(ReplayMod core, PacketListener packetListener, boolean autoStart) { this.core = core; this.packetListener = packetListener; - paused = stopped = !core.getSettingsRegistry().get(Setting.AUTO_START_RECORDING); + paused = stopped = !autoStart; updateState(); } diff --git a/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java b/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java index cd09a29b..ba6fdec0 100644 --- a/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java +++ b/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java @@ -4,6 +4,7 @@ import com.replaymod.core.ReplayMod; import com.replaymod.core.utils.ModCompat; import com.replaymod.core.utils.Utils; import com.replaymod.editor.gui.MarkerProcessor; +import com.replaymod.recording.ServerInfoExt; import com.replaymod.recording.Setting; import com.replaymod.recording.gui.GuiRecordingControls; import com.replaymod.recording.gui.GuiRecordingOverlay; @@ -15,6 +16,7 @@ import com.replaymod.replaystudio.replay.ZipReplayFile; import com.replaymod.replaystudio.studio.ReplayStudio; import io.netty.channel.Channel; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ServerInfo; import net.minecraft.network.ClientConnection; import org.apache.logging.log4j.Logger; @@ -89,6 +91,7 @@ public class ConnectionEventHandler { } String worldName; + boolean autoStart = core.getSettingsRegistry().get(Setting.AUTO_START_RECORDING); if (local) { //#if MC>=11600 worldName = mc.getServer().getSaveProperties().getLevelName(); @@ -96,7 +99,13 @@ public class ConnectionEventHandler { //$$ worldName = mc.getServer().getLevelName(); //#endif } else if (mc.getCurrentServerEntry() != null) { - worldName = mc.getCurrentServerEntry().address; + ServerInfo serverInfo = mc.getCurrentServerEntry(); + worldName = serverInfo.address; + + Boolean autoStartServer = ServerInfoExt.from(serverInfo).getAutoRecording(); + if (autoStartServer != null) { + autoStart = autoStartServer; + } //#if MC>=11100 } else if (mc.isConnectedToRealms()) { // we can't access the server name without tapping too deep in the Realms Library @@ -107,6 +116,11 @@ public class ConnectionEventHandler { return; } + if (ReplayMod.isMinimalMode()) { + // Recording controls are not supported in minimal mode, so always auto-start + autoStart = true; + } + File folder = core.getReplayFolder(); String name = sdf.format(Calendar.getInstance().getTime()); @@ -128,13 +142,13 @@ public class ConnectionEventHandler { recordingEventHandler = new RecordingEventHandler(packetListener); recordingEventHandler.register(); - guiControls = new GuiRecordingControls(core, packetListener); + guiControls = new GuiRecordingControls(core, packetListener, autoStart); guiControls.register(); guiOverlay = new GuiRecordingOverlay(mc, core.getSettingsRegistry(), guiControls); guiOverlay.register(); - if (core.getSettingsRegistry().get(Setting.AUTO_START_RECORDING) || ReplayMod.isMinimalMode()) { + if (autoStart) { core.printInfoToChat("replaymod.chat.recordingstarted"); } else { packetListener.addMarker(MarkerProcessor.MARKER_NAME_START_CUT, 0); diff --git a/src/main/java/com/replaymod/recording/handler/GuiHandler.java b/src/main/java/com/replaymod/recording/handler/GuiHandler.java index 074786c3..4d3cc37e 100644 --- a/src/main/java/com/replaymod/recording/handler/GuiHandler.java +++ b/src/main/java/com/replaymod/recording/handler/GuiHandler.java @@ -2,14 +2,23 @@ package com.replaymod.recording.handler; import com.replaymod.core.ReplayMod; import com.replaymod.core.SettingsRegistry; +import com.replaymod.core.gui.GuiReplayButton; +import com.replaymod.recording.ServerInfoExt; import com.replaymod.recording.Setting; +import com.replaymod.recording.mixin.AddServerScreenAccessor; import de.johni0702.minecraft.gui.container.GuiScreen; import de.johni0702.minecraft.gui.container.VanillaGuiScreen; +import de.johni0702.minecraft.gui.element.GuiButton; import de.johni0702.minecraft.gui.element.GuiCheckbox; +import de.johni0702.minecraft.gui.element.GuiToggleButton; import de.johni0702.minecraft.gui.layout.CustomLayout; +import de.johni0702.minecraft.gui.popup.GuiInfoPopup; import de.johni0702.minecraft.gui.utils.EventRegistrations; +import net.minecraft.client.gui.screen.AddServerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.world.SelectWorldScreen; +import net.minecraft.client.network.ServerInfo; +import net.minecraft.client.resource.language.I18n; //#if FABRIC>=1 import de.johni0702.minecraft.gui.versions.callbacks.InitScreenCallback; @@ -59,5 +68,34 @@ public class GuiHandler extends EventRegistrations { } }).addElements(null, recordingCheckbox); } + + if (gui instanceof AddServerScreen) { + VanillaGuiScreen vanillaGui = VanillaGuiScreen.setup(gui); + GuiButton replayButton = new GuiReplayButton().onClick(() -> { + ServerInfo serverInfo = ((AddServerScreenAccessor) gui).getServer(); + ServerInfoExt serverInfoExt = ServerInfoExt.from(serverInfo); + Boolean state = serverInfoExt.getAutoRecording(); + GuiToggleButton autoRecording = new GuiToggleButton() + .setI18nLabel("replaymod.gui.settings.autostartrecording") + .setValues( + I18n.translate("replaymod.gui.settings.default"), + I18n.translate("options.off"), + I18n.translate("options.on") + ) + .setSelected(state == null ? 0 : state ? 2 : 1); + autoRecording.onClick(() -> { + int selected = autoRecording.getSelected(); + serverInfoExt.setAutoRecording(selected == 0 ? null : selected == 2); + }); + GuiInfoPopup.open(vanillaGui, autoRecording); + }); + vanillaGui.setLayout(new CustomLayout() { + @Override + protected void layout(GuiScreen container, int width, int height) { + size(replayButton, 20, 20); + pos(replayButton, width - width(replayButton) - 5, 5); + } + }).addElements(null, replayButton); + } } } diff --git a/src/main/java/com/replaymod/recording/mixin/AddServerScreenAccessor.java b/src/main/java/com/replaymod/recording/mixin/AddServerScreenAccessor.java new file mode 100644 index 00000000..b8941123 --- /dev/null +++ b/src/main/java/com/replaymod/recording/mixin/AddServerScreenAccessor.java @@ -0,0 +1,12 @@ +package com.replaymod.recording.mixin; + +import net.minecraft.client.gui.screen.AddServerScreen; +import net.minecraft.client.network.ServerInfo; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(AddServerScreen.class) +public interface AddServerScreenAccessor { + @Accessor + ServerInfo getServer(); +} diff --git a/src/main/java/com/replaymod/recording/mixin/MixinServerInfo.java b/src/main/java/com/replaymod/recording/mixin/MixinServerInfo.java new file mode 100644 index 00000000..f9107228 --- /dev/null +++ b/src/main/java/com/replaymod/recording/mixin/MixinServerInfo.java @@ -0,0 +1,47 @@ +package com.replaymod.recording.mixin; + +import com.replaymod.recording.ServerInfoExt; +import net.minecraft.client.network.ServerInfo; +import net.minecraft.nbt.CompoundTag; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ServerInfo.class) +public abstract class MixinServerInfo implements ServerInfoExt { + private Boolean autoRecording; + + @Override + public Boolean getAutoRecording() { + return autoRecording; + } + + @Override + public void setAutoRecording(Boolean autoRecording) { + this.autoRecording = autoRecording; + } + + @Inject(method = "serialize", at = @At("RETURN")) + private void serialize(CallbackInfoReturnable ci) { + CompoundTag tag = ci.getReturnValue(); + if (autoRecording != null) { + tag.putBoolean("autoRecording", autoRecording); + } + } + + @Inject(method = "deserialize", at = @At("RETURN")) + private static void deserialize(CompoundTag tag, CallbackInfoReturnable ci) { + ServerInfoExt serverInfo = ServerInfoExt.from(ci.getReturnValue()); + if (tag.contains("autoRecording")) { + serverInfo.setAutoRecording(tag.getBoolean("autoRecording")); + } + } + + @Inject(method = "copyFrom", at = @At("RETURN")) + public void copyFrom(ServerInfo serverInfo, CallbackInfo ci) { + ServerInfoExt from = ServerInfoExt.from(serverInfo); + this.autoRecording = from.getAutoRecording(); + } +} diff --git a/src/main/resources/assets/replaymod/lang b/src/main/resources/assets/replaymod/lang index 0f708bbc..f1663f04 160000 --- a/src/main/resources/assets/replaymod/lang +++ b/src/main/resources/assets/replaymod/lang @@ -1 +1 @@ -Subproject commit 0f708bbcfb95ce400064e3b98a81320ddca05a00 +Subproject commit f1663f04f97bde22f3a9d53ddb28485836ac91c6 diff --git a/src/main/resources/mixins.recording.replaymod.json b/src/main/resources/mixins.recording.replaymod.json index 09b96cf0..e6c9ee41 100644 --- a/src/main/resources/mixins.recording.replaymod.json +++ b/src/main/resources/mixins.recording.replaymod.json @@ -4,11 +4,13 @@ "mixins": [], "server": [], "client": [ + "AddServerScreenAccessor", "EntityLivingBaseAccessor", "IntegratedServerAccessor", "NetworkManagerAccessor", "SPacketSpawnMobAccessor", "SPacketSpawnPlayerAccessor", + "MixinServerInfo", //#if MC>=11400 "MixinDownloadingPackFinder", "MixinMouseHelper", diff --git a/versions/1.14.4-forge/mapping.txt b/versions/1.14.4-forge/mapping.txt index 1d242ae4..d2db8300 100644 --- a/versions/1.14.4-forge/mapping.txt +++ b/versions/1.14.4-forge/mapping.txt @@ -1,3 +1,4 @@ +net.minecraft.client.gui.screen.AddServerScreen net.minecraft.client.gui.GuiScreenAddServer net.minecraft.resources.AbstractResourcePack net.minecraft.client.resources.AbstractResourcePack net.minecraft.resources.FolderPack net.minecraft.client.resources.FolderResourcePack net.minecraft.client.resources.DownloadingPackFinder net.minecraft.client.resources.ResourcePackRepository