From 28dcfbeac343245fb32620262ef15ca355dd3280 Mon Sep 17 00:00:00 2001 From: c0de Date: Wed, 22 Mar 2023 23:20:13 +0000 Subject: [PATCH] Base functions and first module (#1) This is a working baseline Reviewed-on: https://c0de.dev/c0de/minecraft-mod/pulls/1 --- LICENSE | 122 +----------------- README.md | 6 +- gradle.properties | 6 +- .../java/dev/c0de/minecraft/c0deFoxMod.java | 13 +- .../dev/c0de/minecraft/client/Module.java | 48 +++++++ .../minecraft/client/c0deFoxModClient.java | 43 ++++++ .../minecraft/client/modules/Fullbright.java | 37 ++++++ .../c0de/minecraft/config/ClientConfig.java | 6 + .../c0de/minecraft/config/SimpleConfig.java | 80 ++++++++++++ .../c0de/minecraft/mixin/BrightnessMixin.java | 37 ++++++ .../c0de/minecraft/mixin/c0deFoxMixin.java | 5 +- .../resources/assets/c0defox/lang/en_us.json | 4 + src/main/resources/c0defox.mixins.json | 1 + src/main/resources/fabric.mod.json | 11 +- 14 files changed, 279 insertions(+), 140 deletions(-) create mode 100644 src/main/java/dev/c0de/minecraft/client/Module.java create mode 100644 src/main/java/dev/c0de/minecraft/client/c0deFoxModClient.java create mode 100644 src/main/java/dev/c0de/minecraft/client/modules/Fullbright.java create mode 100644 src/main/java/dev/c0de/minecraft/config/ClientConfig.java create mode 100644 src/main/java/dev/c0de/minecraft/config/SimpleConfig.java create mode 100644 src/main/java/dev/c0de/minecraft/mixin/BrightnessMixin.java create mode 100644 src/main/resources/assets/c0defox/lang/en_us.json diff --git a/LICENSE b/LICENSE index 0e259d4..c91808e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,121 +1,3 @@ -Creative Commons Legal Code +MIT License -CC0 1.0 Universal - - CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE - LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN - ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS - INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES - REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS - PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM - THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED - HEREUNDER. - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator -and subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for -the purpose of contributing to a commons of creative, cultural and -scientific works ("Commons") that the public can reliably and without fear -of later claims of infringement build upon, modify, incorporate in other -works, reuse and redistribute as freely as possible in any form whatsoever -and for any purposes, including without limitation commercial purposes. -These owners may contribute to the Commons to promote the ideal of a free -culture and the further production of creative, cultural and scientific -works, or to gain reputation or greater distribution for their Work in -part through the use and efforts of others. - -For these and/or other purposes and motivations, and without any -expectation of additional consideration or compensation, the person -associating CC0 with a Work (the "Affirmer"), to the extent that he or she -is an owner of Copyright and Related Rights in the Work, voluntarily -elects to apply CC0 to the Work and publicly distribute the Work under its -terms, with knowledge of his or her Copyright and Related Rights in the -Work and the meaning and intended legal effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not -limited to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, - communicate, and translate a Work; - ii. moral rights retained by the original author(s) and/or performer(s); -iii. publicity and privacy rights pertaining to a person's image or - likeness depicted in a Work; - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - v. rights protecting the extraction, dissemination, use and reuse of data - in a Work; - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation - thereof, including any amended or successor version of such - directive); and -vii. other similar, equivalent or corresponding rights throughout the - world based on applicable law or treaty, and any national - implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention -of, applicable law, Affirmer hereby overtly, fully, permanently, -irrevocably and unconditionally waives, abandons, and surrenders all of -Affirmer's Copyright and Related Rights and associated claims and causes -of action, whether now known or unknown (including existing as well as -future claims and causes of action), in the Work (i) in all territories -worldwide, (ii) for the maximum duration provided by applicable law or -treaty (including future time extensions), (iii) in any current or future -medium and for any number of copies, and (iv) for any purpose whatsoever, -including without limitation commercial, advertising or promotional -purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each -member of the public at large and to the detriment of Affirmer's heirs and -successors, fully intending that such Waiver shall not be subject to -revocation, rescission, cancellation, termination, or any other legal or -equitable action to disrupt the quiet enjoyment of the Work by the public -as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason -be judged legally invalid or ineffective under applicable law, then the -Waiver shall be preserved to the maximum extent permitted taking into -account Affirmer's express Statement of Purpose. In addition, to the -extent the Waiver is so judged Affirmer hereby grants to each affected -person a royalty-free, non transferable, non sublicensable, non exclusive, -irrevocable and unconditional license to exercise Affirmer's Copyright and -Related Rights in the Work (i) in all territories worldwide, (ii) for the -maximum duration provided by applicable law or treaty (including future -time extensions), (iii) in any current or future medium and for any number -of copies, and (iv) for any purpose whatsoever, including without -limitation commercial, advertising or promotional purposes (the -"License"). The License shall be deemed effective as of the date CC0 was -applied by Affirmer to the Work. Should any part of the License for any -reason be judged legally invalid or ineffective under applicable law, such -partial invalidity or ineffectiveness shall not invalidate the remainder -of the License, and in such case Affirmer hereby affirms that he or she -will not (i) exercise any of his or her remaining Copyright and Related -Rights in the Work or (ii) assert any associated claims and causes of -action with respect to the Work, in either case contrary to Affirmer's -express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - b. Affirmer offers the Work as-is and makes no representations or - warranties of any kind concerning the Work, express, implied, - statutory or otherwise, including without limitation warranties of - title, merchantability, fitness for a particular purpose, non - infringement, or the absence of latent or other defects, accuracy, or - the present or absence of errors, whether or not discoverable, all to - the greatest extent permissible under applicable law. - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without - limitation any person's Copyright and Related Rights in the Work. - Further, Affirmer disclaims responsibility for obtaining any necessary - consents, permissions or other rights required for any use of the - Work. - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to - this CC0 or use of the Work. +# TODO: Add license diff --git a/README.md b/README.md index fd96346..01d916f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# Fabric Example Mod +# c0de's mod + +A collection of mods for minecraft ## Setup @@ -6,4 +8,4 @@ For setup instructions please see the [fabric wiki page](https://fabricmc.net/wi ## License -This template is available under the CC0 license. Feel free to learn from it and incorporate it in your own projects. +This mod is released under the MIT license. diff --git a/gradle.properties b/gradle.properties index 710b01f..87ec33d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,9 @@ org.gradle.parallel=true loader_version=0.14.17 # Mod Properties - mod_version = 1.0.0 - maven_group = com.example - archives_base_name = fabric-example-mod + mod_version = 0.0.1 + maven_group = dev.c0de + archives_base_name = minecraft-mod # Dependencies fabric_version=0.75.3+1.19.4 diff --git a/src/main/java/dev/c0de/minecraft/c0deFoxMod.java b/src/main/java/dev/c0de/minecraft/c0deFoxMod.java index 3c6453f..b7736c0 100644 --- a/src/main/java/dev/c0de/minecraft/c0deFoxMod.java +++ b/src/main/java/dev/c0de/minecraft/c0deFoxMod.java @@ -1,19 +1,14 @@ package dev.c0de.minecraft; +import dev.c0de.minecraft.config.SimpleConfig; import net.fabricmc.api.ModInitializer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class c0deFoxMod implements ModInitializer { - public static final Logger LOGGER = LoggerFactory.getLogger("c0defox"); + + public static SimpleConfig config; @Override public void onInitialize() { - // This code runs as soon as Minecraft is in a mod-load-ready state. - // However, some things (like resources) may still be uninitialized. - // Proceed with mild caution. - - LOGGER.info("Hello world!"); + config = new SimpleConfig("c0defox"); } } diff --git a/src/main/java/dev/c0de/minecraft/client/Module.java b/src/main/java/dev/c0de/minecraft/client/Module.java new file mode 100644 index 0000000..e785330 --- /dev/null +++ b/src/main/java/dev/c0de/minecraft/client/Module.java @@ -0,0 +1,48 @@ +package dev.c0de.minecraft.client; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; + +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; + +public abstract class Module { + + protected KeyBinding key; + protected boolean state; + + public void onTick(MinecraftClient client) { + } + + public void onToggle(MinecraftClient client) { + } + + public void registerKey(String translationKey, int glfw_key, String category) { + this.key = KeyBindingHelper.registerKeyBinding(new KeyBinding( + translationKey, + InputUtil.Type.KEYSYM, + glfw_key, + category + )); + } + + public void setState(boolean state) { + this.state = state; + } + + public KeyBinding getKey() { + return this.key; + } + + public void toggleKey() { + if (this.key != null) { + if (this.key.wasPressed()) { + this.setState(!this.isState()); + } + } + } + + public boolean isState() { + return this.state; + } +} \ No newline at end of file diff --git a/src/main/java/dev/c0de/minecraft/client/c0deFoxModClient.java b/src/main/java/dev/c0de/minecraft/client/c0deFoxModClient.java new file mode 100644 index 0000000..c87da95 --- /dev/null +++ b/src/main/java/dev/c0de/minecraft/client/c0deFoxModClient.java @@ -0,0 +1,43 @@ +package dev.c0de.minecraft.client; + +import net.fabricmc.api.ClientModInitializer; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.minecraft.client.MinecraftClient; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import dev.c0de.minecraft.client.modules.Fullbright; + +@Environment(EnvType.CLIENT) +public class c0deFoxModClient implements ClientModInitializer { + public static final Logger LOGGER = LoggerFactory.getLogger("c0defox"); + + private static c0deFoxModClient self; + + private static Module fullbright; + + @Override + public void onInitializeClient() { + ClientTickEvents.END_CLIENT_TICK.register(this::tick); + + self = this; + + fullbright = new Fullbright(); + + LOGGER.info("Ready"); + } + + public static c0deFoxModClient getSelf() { + return self; + } + + // Called on every game tick + public void tick(MinecraftClient client) { + fullbright.onTick(client); + } + +} diff --git a/src/main/java/dev/c0de/minecraft/client/modules/Fullbright.java b/src/main/java/dev/c0de/minecraft/client/modules/Fullbright.java new file mode 100644 index 0000000..b3284f9 --- /dev/null +++ b/src/main/java/dev/c0de/minecraft/client/modules/Fullbright.java @@ -0,0 +1,37 @@ +package dev.c0de.minecraft.client.modules; + +import dev.c0de.minecraft.c0deFoxMod; +import dev.c0de.minecraft.client.Module; +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.Text; + +import org.lwjgl.glfw.GLFW; + +public class Fullbright extends Module { + double DEFAULT = 1.0; + + public Fullbright() { + this.registerKey("key.c0defox.fullbright", GLFW.GLFW_KEY_B, "key.categories.c0defox"); + } + + @Override + public void onTick(MinecraftClient client) { + this.toggleKey(); + + if (this.isState()) { + this.update(client, c0deFoxMod.config.getConfig().FULLBRIGHT_GAMMA); + return; + } + + this.update(client, DEFAULT); + } + + private void update(MinecraftClient client, double value) { + if (client == null) return; + if (client.options.getGamma().getValue() == value) return; + + client.options.getGamma().setValue(value); + + if (client.player != null) client.player.sendMessage(Text.of(String.valueOf(value)), true); + } +} diff --git a/src/main/java/dev/c0de/minecraft/config/ClientConfig.java b/src/main/java/dev/c0de/minecraft/config/ClientConfig.java new file mode 100644 index 0000000..a83bf7e --- /dev/null +++ b/src/main/java/dev/c0de/minecraft/config/ClientConfig.java @@ -0,0 +1,6 @@ +package dev.c0de.minecraft.config; + +// Configuration options for the client +public class ClientConfig { + public double FULLBRIGHT_GAMMA = 5.5; +} diff --git a/src/main/java/dev/c0de/minecraft/config/SimpleConfig.java b/src/main/java/dev/c0de/minecraft/config/SimpleConfig.java new file mode 100644 index 0000000..fa67faf --- /dev/null +++ b/src/main/java/dev/c0de/minecraft/config/SimpleConfig.java @@ -0,0 +1,80 @@ +package dev.c0de.minecraft.config; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import net.fabricmc.loader.api.FabricLoader; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; + +public class SimpleConfig { + + private static final Logger LOGGER = LogManager.getLogger("SimpleConfig"); + private boolean broken = false; + private final File file; + + private ClientConfig config = new ClientConfig(); + + public ClientConfig getConfig() { + return config; + } + + public void createConfig() throws IOException { + + // try creating missing files + file.getParentFile().mkdirs(); + if (Files.notExists(file.toPath())) + Files.createFile(file.toPath()); + + // write default config data + Gson gson = new GsonBuilder() + .enableComplexMapKeySerialization() + .setPrettyPrinting() + .create(); + + PrintWriter writer = new PrintWriter(file, StandardCharsets.UTF_8); + gson.toJson(config, writer); + writer.close(); + } + + private void loadConfig() throws IOException { + Gson gson = new Gson(); + Reader reader = Files.newBufferedReader(file.toPath()); + config = gson.fromJson(reader, ClientConfig.class); + reader.close(); + } + + public SimpleConfig(String modID) { + Path path = FabricLoader.getInstance().getConfigDir(); + file = new File(path.toAbsolutePath().toString(), modID + ".json"); + + if (!file.exists()) { + LOGGER.info(modID + " is missing, generating default one..."); + + try { + createConfig(); + } catch (IOException e) { + LOGGER.error(modID + " failed to generate!"); + LOGGER.trace(e); + broken = true; + } + } + + if (!broken) { + try { + loadConfig(); + } catch (Exception e) { + LOGGER.error(modID + " failed to load!"); + LOGGER.trace(e); + broken = true; + } + } + } +} \ No newline at end of file diff --git a/src/main/java/dev/c0de/minecraft/mixin/BrightnessMixin.java b/src/main/java/dev/c0de/minecraft/mixin/BrightnessMixin.java new file mode 100644 index 0000000..a4cfba4 --- /dev/null +++ b/src/main/java/dev/c0de/minecraft/mixin/BrightnessMixin.java @@ -0,0 +1,37 @@ +package dev.c0de.minecraft.mixin; + +import com.mojang.serialization.Codec; +import net.minecraft.client.option.SimpleOption; +import net.minecraft.client.resource.language.I18n; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(SimpleOption.class) +public class BrightnessMixin { + @Shadow @Final + Text text; + + @Shadow + T value; + + @Inject(method = "getCodec", at = @At("HEAD"), cancellable = true) + private void returnFakeCodec(CallbackInfoReturnable> info) { + if (text.getString().equals(I18n.translate("options.gamma"))) { + info.setReturnValue(Codec.DOUBLE); + } + } + + @Inject(method = "setValue", at = @At("HEAD"), cancellable = true) + private void setRealValue(T value, CallbackInfo info) { + if (text.getString().equals(I18n.translate("options.gamma"))) { + this.value = value; + info.cancel(); + } + } +} \ No newline at end of file diff --git a/src/main/java/dev/c0de/minecraft/mixin/c0deFoxMixin.java b/src/main/java/dev/c0de/minecraft/mixin/c0deFoxMixin.java index 5b33d5b..7b42a2a 100644 --- a/src/main/java/dev/c0de/minecraft/mixin/c0deFoxMixin.java +++ b/src/main/java/dev/c0de/minecraft/mixin/c0deFoxMixin.java @@ -1,6 +1,7 @@ package dev.c0de.minecraft.mixin; -import dev.c0de.minecraft.c0deFoxMod; +// import dev.c0de.minecraft.c0deFoxMod; + import net.minecraft.client.gui.screen.TitleScreen; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -11,7 +12,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; public class c0deFoxMixin { @Inject(at = @At("HEAD"), method = "init()V") private void init(CallbackInfo info) { - c0deFoxMod.LOGGER.info("This line is printed by an example mod mixin!"); + // c0deFoxMod.LOGGER.info("This line is printed by an example mod mixin!"); } } diff --git a/src/main/resources/assets/c0defox/lang/en_us.json b/src/main/resources/assets/c0defox/lang/en_us.json new file mode 100644 index 0000000..ab2de31 --- /dev/null +++ b/src/main/resources/assets/c0defox/lang/en_us.json @@ -0,0 +1,4 @@ +{ + "key.categories.c0defox": "c0de's mods", + "key.c0defox.fullbright": "Fullbright" +} \ No newline at end of file diff --git a/src/main/resources/c0defox.mixins.json b/src/main/resources/c0defox.mixins.json index 8826d0d..f27bd9b 100644 --- a/src/main/resources/c0defox.mixins.json +++ b/src/main/resources/c0defox.mixins.json @@ -6,6 +6,7 @@ "mixins": [ ], "client": [ + "BrightnessMixin", "c0deFoxMixin" ], "injectors": { diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index fb3c58c..5cfc8be 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -14,22 +14,25 @@ }, "license": "MIT", - "icon": "assets/modid/icon.png", + "icon": "assets/c0defox/icon.png", - "environment": "*", + "environment": "client", "entrypoints": { "main": [ "dev.c0de.minecraft.c0deFoxMod" + ], + "client": [ + "dev.c0de.minecraft.client.c0deFoxModClient" ] }, "mixins": [ - "modid.mixins.json" + "c0defox.mixins.json" ], "depends": { "fabricloader": ">=0.14.17", "fabric-api": "*", - "minecraft": "~1.19.4", + "minecraft": ">=1.19.4", "java": ">=17" }, "suggests": {