diff --git a/common/build.gradle b/common/build.gradle index c3c84a3e..12c3ccf4 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -8,9 +8,6 @@ loom { dependencies { modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" - - modApi "dev.architectury:architectury:${rootProject.architectury_version}" - modApi "me.shedaniel.cloth:cloth-config:${rootProject.cloth_version}" } diff --git a/common/src/main/java/net/xolt/freecam/Freecam.java b/common/src/main/java/net/xolt/freecam/Freecam.java index b6aaaca1..354c862c 100644 --- a/common/src/main/java/net/xolt/freecam/Freecam.java +++ b/common/src/main/java/net/xolt/freecam/Freecam.java @@ -1,14 +1,11 @@ package net.xolt.freecam; -import dev.architectury.event.events.client.ClientTickEvent; -import dev.architectury.registry.client.keymappings.KeyMappingRegistry; import me.shedaniel.autoconfig.AutoConfig; import net.minecraft.client.MinecraftClient; import net.minecraft.client.input.Input; import net.minecraft.client.input.KeyboardInput; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.option.Perspective; -import net.minecraft.client.util.InputUtil; import net.minecraft.text.Text; import net.minecraft.util.math.ChunkPos; import net.xolt.freecam.config.ModConfig; @@ -17,22 +14,14 @@ import org.lwjgl.glfw.GLFW; import java.util.HashMap; -import java.util.stream.Stream; + +import static net.xolt.freecam.config.ModBindings.*; public class Freecam { public static final MinecraftClient MC = MinecraftClient.getInstance(); public static final String MOD_ID = "freecam"; - public static final KeyBinding KEY_TOGGLE = new KeyBinding( - "key.freecam.toggle", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_F4, "category.freecam.freecam"); - public static final KeyBinding KEY_PLAYER_CONTROL = new KeyBinding( - "key.freecam.playerControl", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, "category.freecam.freecam"); - public static final KeyBinding KEY_TRIPOD_RESET = new KeyBinding( - "key.freecam.tripodReset", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, "category.freecam.freecam"); - public static final KeyBinding KEY_CONFIG_GUI = new KeyBinding( - "key.freecam.configGui", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, "category.freecam.freecam"); - private static boolean freecamEnabled = false; private static boolean tripodEnabled = false; private static boolean playerControlEnabled = false; @@ -44,40 +33,61 @@ public class Freecam { private static HashMap end_tripods = new HashMap<>(); private static Perspective rememberedF5 = null; - public static void init() { - ModConfig.init(); - Stream.of(KEY_TOGGLE, KEY_PLAYER_CONTROL, KEY_TRIPOD_RESET, KEY_CONFIG_GUI).forEach(KeyMappingRegistry::register); - - ClientTickEvent.CLIENT_POST.register(client -> { - if (KEY_TRIPOD_RESET.isPressed()) { - for (KeyBinding hotbarKey : MC.options.hotbarKeys) { - while (hotbarKey.wasPressed()) { - resetCamera(hotbarKey.getDefaultKey().getCode()); - while (KEY_TRIPOD_RESET.wasPressed()) {} - } - } + public static void preTick(MinecraftClient mc) { + if (isEnabled()) { + // Disable if the previous tick asked us to + if (disableNextTick()) { + toggle(); + disableNextTick = false; } - if (KEY_TOGGLE.isPressed()) { - for (KeyBinding hotbarKey : MC.options.hotbarKeys) { - while (hotbarKey.wasPressed()) { - toggleTripod(hotbarKey.getDefaultKey().getCode()); - while (KEY_TOGGLE.wasPressed()) {} - } - } - } else if (KEY_TOGGLE.wasPressed()) { - toggle(); - while (KEY_TOGGLE.wasPressed()) {} + // Prevent player from being controlled when freecam is enabled + if (mc.player != null && mc.player.input instanceof KeyboardInput && !isPlayerControlEnabled()) { + Input input = new Input(); + input.sneaking = mc.player.input.sneaking; // Makes player continue to sneak after freecam is enabled. + mc.player.input = input; } - while (KEY_PLAYER_CONTROL.wasPressed()) { - switchControls(); + mc.gameRenderer.setRenderHand(ModConfig.INSTANCE.visual.showHand); + } + } + + public static void postTick(MinecraftClient mc) { + if (KEY_TRIPOD_RESET.isPressed()) { + for (KeyBinding hotbarKey : mc.options.hotbarKeys) { + while (hotbarKey.wasPressed()) { + resetCamera(hotbarKey.getDefaultKey().getCode()); + while (KEY_TRIPOD_RESET.wasPressed()) {} + } } + } - while (KEY_CONFIG_GUI.wasPressed()) { - MC.setScreen(AutoConfig.getConfigScreen(ModConfig.class, MC.currentScreen).get()); + if (KEY_TOGGLE.isPressed()) { + for (KeyBinding hotbarKey : mc.options.hotbarKeys) { + while (hotbarKey.wasPressed()) { + toggleTripod(hotbarKey.getDefaultKey().getCode()); + while (KEY_TOGGLE.wasPressed()) {} + } } - }); + } else if (KEY_TOGGLE.wasPressed()) { + toggle(); + while (KEY_TOGGLE.wasPressed()) {} + } + + while (KEY_PLAYER_CONTROL.wasPressed()) { + switchControls(); + } + + while (KEY_CONFIG_GUI.wasPressed()) { + mc.setScreen(AutoConfig.getConfigScreen(ModConfig.class, mc.currentScreen).get()); + } + } + + public static void onDisconnect() { + if (isEnabled()) { + toggle(); + } + clearTripods(); } public static void toggle() { diff --git a/common/src/main/java/net/xolt/freecam/config/ModBindings.java b/common/src/main/java/net/xolt/freecam/config/ModBindings.java new file mode 100644 index 00000000..21c45897 --- /dev/null +++ b/common/src/main/java/net/xolt/freecam/config/ModBindings.java @@ -0,0 +1,100 @@ +package net.xolt.freecam.config; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.Objects; +import java.util.Spliterator; +import java.util.function.Consumer; + +import static org.lwjgl.glfw.GLFW.GLFW_KEY_F4; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_UNKNOWN; + +public enum ModBindings { + + KEY_TOGGLE("toggle", GLFW_KEY_F4), + KEY_PLAYER_CONTROL("playerControl"), + KEY_TRIPOD_RESET("tripodReset"), + KEY_CONFIG_GUI("configGui"); + + private final Supplier lazyBinding; + + ModBindings(String translationKey) { + this(translationKey, InputUtil.Type.KEYSYM, GLFW_KEY_UNKNOWN); + } + + ModBindings(String translationKey, int code) { + this(translationKey, InputUtil.Type.KEYSYM, code); + } + + ModBindings(String translationKey, InputUtil.Type type) { + this(translationKey, type, GLFW_KEY_UNKNOWN); + } + + ModBindings(String translationKey, InputUtil.Type type, int code) { + this.lazyBinding = Suppliers.memoize(() -> + new KeyBinding("key.freecam." + translationKey, type, code, "category.freecam.freecam")); + } + + /** + * @return the result of calling {@link KeyBinding#isPressed()} on the represented {@link KeyBinding}. + * @see KeyBinding#isPressed() + */ + public boolean isPressed() { + return get().isPressed(); + } + + /** + * @return the result of calling {@link KeyBinding#wasPressed()} on the represented {@link KeyBinding}. + * @see KeyBinding#wasPressed() + */ + public boolean wasPressed() { + return get().wasPressed(); + } + + /** + * Lazily get the actual {@link KeyBinding} represented by this enum value. + *

+ * Values are constructed if they haven't been already. + * + * @return the actual {@link KeyBinding}. + */ + public KeyBinding get() { + return lazyBinding.get(); + } + + /** + * Calls {@code action} using each {@link KeyBinding} owned by this enum. + *

+ * Values are constructed if they haven't been already. + *

+ * Static implementation of {@link Iterable#forEach(Consumer)}. + */ + public static void forEach(@NotNull Consumer action) { + Objects.requireNonNull(action); + iterator().forEachRemaining(action); + } + + /** + * Static implementation of {@link Iterable#iterator()}. + */ + public static @NotNull Iterator iterator() { + return Arrays.stream(values()) + .map(ModBindings::get) + .iterator(); + } + + /** + * Static implementation of {@link Iterable#spliterator()}. + */ + public static @NotNull Spliterator spliterator() { + return Arrays.stream(values()) + .map(ModBindings::get) + .spliterator(); + } +} diff --git a/common/src/main/java/net/xolt/freecam/mixins/ClientConnectionMixin.java b/common/src/main/java/net/xolt/freecam/mixins/ClientConnectionMixin.java index d7812ca3..cce44073 100644 --- a/common/src/main/java/net/xolt/freecam/mixins/ClientConnectionMixin.java +++ b/common/src/main/java/net/xolt/freecam/mixins/ClientConnectionMixin.java @@ -13,9 +13,6 @@ public class ClientConnectionMixin { // Disables freecam if the player disconnects. @Inject(method = "handleDisconnection", at = @At("HEAD")) private void onHandleDisconnection(CallbackInfo ci) { - if (Freecam.isEnabled()) { - Freecam.toggle(); - } - Freecam.clearTripods(); + Freecam.onDisconnect(); } } diff --git a/common/src/main/java/net/xolt/freecam/mixins/MinecraftClientMixin.java b/common/src/main/java/net/xolt/freecam/mixins/MinecraftClientMixin.java index dcf00d60..56cc1cb8 100644 --- a/common/src/main/java/net/xolt/freecam/mixins/MinecraftClientMixin.java +++ b/common/src/main/java/net/xolt/freecam/mixins/MinecraftClientMixin.java @@ -1,8 +1,6 @@ package net.xolt.freecam.mixins; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.input.Input; -import net.minecraft.client.input.KeyboardInput; import net.xolt.freecam.Freecam; import net.xolt.freecam.config.ModConfig; import org.spongepowered.asm.mixin.Mixin; @@ -11,29 +9,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import static net.xolt.freecam.Freecam.MC; +import static net.xolt.freecam.config.ModBindings.KEY_TOGGLE; +import static net.xolt.freecam.config.ModBindings.KEY_TRIPOD_RESET; @Mixin(MinecraftClient.class) public class MinecraftClientMixin { - // Prevents player from being controlled when freecam is enabled. - @Inject(method = "tick", at = @At("HEAD")) - private void onTick(CallbackInfo ci) { - if (Freecam.isEnabled()) { - if (MC.player != null && MC.player.input instanceof KeyboardInput && !Freecam.isPlayerControlEnabled()) { - Input input = new Input(); - input.sneaking = MC.player.input.sneaking; // Makes player continue to sneak after freecam is enabled. - MC.player.input = input; - } - MC.gameRenderer.setRenderHand(ModConfig.INSTANCE.visual.showHand); - - if (Freecam.disableNextTick()) { - Freecam.toggle(); - Freecam.setDisableNextTick(false); - } - } - } - // Prevents attacks when allowInteract is disabled. @Inject(method = "doAttack", at = @At("HEAD"), cancellable = true) private void onDoAttack(CallbackInfoReturnable cir) { @@ -61,7 +42,7 @@ private void onHandleBlockBreaking(CallbackInfo ci) { // Prevents hotbar keys from changing selected slot when freecam key is held @Inject(method = "handleInputEvents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/KeyBinding;wasPressed()Z", ordinal = 2), cancellable = true) private void onHandleInputEvents(CallbackInfo ci) { - if (Freecam.KEY_TOGGLE.isPressed() || Freecam.KEY_TRIPOD_RESET.isPressed()) { + if (KEY_TOGGLE.isPressed() || KEY_TRIPOD_RESET.isPressed()) { ci.cancel(); } } diff --git a/fabric/build.gradle b/fabric/build.gradle index db14d27a..61d7be60 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -23,9 +23,6 @@ dependencies { modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}" - modApi "dev.architectury:architectury-fabric:${rootProject.architectury_version}" - include "dev.architectury:architectury-fabric:${rootProject.architectury_version}" - modImplementation ("com.terraformersmc:modmenu:${rootProject.modmenu_version}") { exclude module: "fabric-api" } diff --git a/fabric/src/main/java/net/xolt/freecam/fabric/FreecamFabric.java b/fabric/src/main/java/net/xolt/freecam/fabric/FreecamFabric.java index bd357600..5a7a979c 100644 --- a/fabric/src/main/java/net/xolt/freecam/fabric/FreecamFabric.java +++ b/fabric/src/main/java/net/xolt/freecam/fabric/FreecamFabric.java @@ -1,11 +1,18 @@ package net.xolt.freecam.fabric; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.xolt.freecam.Freecam; +import net.xolt.freecam.config.ModBindings; +import net.xolt.freecam.config.ModConfig; public class FreecamFabric implements ClientModInitializer { @Override public void onInitializeClient() { - Freecam.init(); + ModConfig.init(); + ModBindings.forEach(KeyBindingHelper::registerKeyBinding); + ClientTickEvents.START_CLIENT_TICK.register(Freecam::preTick); + ClientTickEvents.END_CLIENT_TICK.register(Freecam::postTick); } } diff --git a/forge/build.gradle b/forge/build.gradle index bdb7d2f8..2bb72e6e 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -30,9 +30,6 @@ configurations { dependencies { forge "net.minecraftforge:forge:${rootProject.forge_version}" - modApi "dev.architectury:architectury-forge:${rootProject.architectury_version}" - include "dev.architectury:architectury-forge:${rootProject.architectury_version}" - modApi "me.shedaniel.cloth:cloth-config-forge:${rootProject.cloth_version}" include "me.shedaniel.cloth:cloth-config-forge:${rootProject.cloth_version}" diff --git a/forge/src/main/java/net/xolt.freecam/forge/FreecamForge.java b/forge/src/main/java/net/xolt.freecam/forge/FreecamForge.java index cfbae9fa..33850bce 100644 --- a/forge/src/main/java/net/xolt.freecam/forge/FreecamForge.java +++ b/forge/src/main/java/net/xolt.freecam/forge/FreecamForge.java @@ -1,26 +1,49 @@ package net.xolt.freecam.forge; -import dev.architectury.platform.forge.EventBuses; import me.shedaniel.autoconfig.AutoConfig; +import net.minecraft.client.MinecraftClient; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.ConfigScreenHandler; +import net.minecraftforge.client.event.RegisterKeyMappingsEvent; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.xolt.freecam.Freecam; +import net.xolt.freecam.config.ModBindings; import net.xolt.freecam.config.ModConfig; @Mod(Freecam.MOD_ID) +@Mod.EventBusSubscriber(bus = Bus.MOD, value = Dist.CLIENT) public class FreecamForge { - public FreecamForge() { - // Register our event bus with Architectury - EventBuses.registerModEventBus(Freecam.MOD_ID, FMLJavaModLoadingContext.get().getModEventBus()); + + @SubscribeEvent + public static void clientSetup(FMLClientSetupEvent event) { + ModConfig.init(); // Register our config screen with Forge ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> new ConfigScreenHandler.ConfigScreenFactory((client, parent) -> - AutoConfig.getConfigScreen(ModConfig.class, parent).get() + AutoConfig.getConfigScreen(ModConfig.class, parent).get() )); + } + + @SubscribeEvent + public static void registerKeymappings(RegisterKeyMappingsEvent event) { + ModBindings.forEach(event::register); + } - // Call our init - Freecam.init(); + @Mod.EventBusSubscriber(bus = Bus.FORGE, value = Dist.CLIENT) + public static class GlobalEventHandler { + @SubscribeEvent(priority = EventPriority.HIGH) + public static void onTick(TickEvent.ClientTickEvent event) { + final MinecraftClient client = MinecraftClient.getInstance(); + switch (event.phase) { + case START -> Freecam.preTick(client); + case END -> Freecam.postTick(client); + } + } } } diff --git a/gradle.properties b/gradle.properties index a070c377..97586372 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,8 +9,6 @@ archives_base_name=freecam mod_version=1.2.1.1 maven_group=net.xolt.freecam -architectury_version=10.0.16 - fabric_loader_version=0.14.25 fabric_api_version=0.91.1+1.20.2