commit 0cffcf35ac9732ea60946799de37413f0e43a85a
Author: tonitch <tonitch@herisson.ovh>
Date:   Fri Mar 14 10:00:24 2025 +0100

    First Commit

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d5f737e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,119 @@
+# User-specific stuff
+.idea/
+
+*.iml
+*.ipr
+*.iws
+
+# IntelliJ
+out/
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+.gradle
+build/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Cache of project
+.gradletasknamecache
+
+**/build/
+
+# Common working directory
+run/
+runs/
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..13cb709
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2025 Tonitch8
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..ab9af64
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,89 @@
+plugins {
+    id 'fabric-loom' version '1.10-SNAPSHOT'
+    id 'maven-publish'
+}
+
+version = project.mod_version
+group = project.maven_group
+
+base {
+    archivesName = project.archives_base_name
+}
+
+
+repositories {
+    // Add repositories to retrieve artifacts from in here.
+    // You should only use this when depending on other mods because
+    // Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
+    // See https://docs.gradle.org/current/userguide/declaring_repositories.html
+    // for more information about repositories.
+}
+
+dependencies {
+    // To change the versions see the gradle.properties file
+    minecraft "com.mojang:minecraft:${project.minecraft_version}"
+    mappings "net.fabricmc:yarn:${project.yarn_mappings}"
+    modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
+
+    modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
+}
+
+processResources {
+    inputs.property "version", project.version
+    inputs.property "minecraft_version", project.minecraft_version
+    inputs.property "loader_version", project.loader_version
+    filteringCharset "UTF-8"
+
+    filesMatching("fabric.mod.json") {
+        expand "version": project.version,
+                "minecraft_version": project.minecraft_version,
+                "loader_version": project.loader_version
+    }
+}
+
+def targetJavaVersion = 17
+tasks.withType(JavaCompile).configureEach {
+    // ensure that the encoding is set to UTF-8, no matter what the system default is
+    // this fixes some edge cases with special characters not displaying correctly
+    // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
+    // If Javadoc is generated, this must be specified in that task too.
+    it.options.encoding = "UTF-8"
+    if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
+        it.options.release.set(targetJavaVersion)
+    }
+}
+
+java {
+    def javaVersion = JavaVersion.toVersion(targetJavaVersion)
+    if (JavaVersion.current() < javaVersion) {
+        toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
+    }
+    // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
+    // if it is present.
+    // If you remove this line, sources will not be generated.
+    withSourcesJar()
+}
+
+jar {
+    from("LICENSE") {
+        rename { "${it}_${project.archivesBaseName}" }
+    }
+}
+
+// configure the maven publication
+publishing {
+    publications {
+        create("mavenJava", MavenPublication) {
+            artifactId = project.archives_base_name
+            from components.java
+        }
+    }
+
+    // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
+    repositories {
+        // Add repositories to publish to here.
+        // Notice: This block does NOT have the same function as the block in the top level.
+        // The repositories here will be used for publishing your artifact, not for
+        // retrieving dependencies.
+    }
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..bcdf2c3
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,14 @@
+# Done to increase the memory available to gradle.
+org.gradle.jvmargs=-Xmx1G
+# Fabric Properties
+# check these on https://modmuss50.me/fabric.html
+minecraft_version=1.20.1
+yarn_mappings=1.20.1+build.10
+loader_version=0.16.10
+# Mod Properties
+mod_version=1.0-SNAPSHOT
+maven_group=ovh.herisson
+archives_base_name=HornOfTheWild
+# Dependencies
+# check this on https://modmuss50.me/fabric.html
+fabric_version=0.92.3+1.20.1
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..e18bc25
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..f91a4fe
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,9 @@
+pluginManagement {
+    repositories {
+        maven {
+            name = 'Fabric'
+            url = 'https://maven.fabricmc.net/'
+        }
+        gradlePluginPortal()
+    }
+}
diff --git a/src/main/java/ovh/herisson/hornofthewild/HornOfTheWild.java b/src/main/java/ovh/herisson/hornofthewild/HornOfTheWild.java
new file mode 100644
index 0000000..2b4b6c9
--- /dev/null
+++ b/src/main/java/ovh/herisson/hornofthewild/HornOfTheWild.java
@@ -0,0 +1,19 @@
+package ovh.herisson.hornofthewild;
+
+import net.fabricmc.api.ModInitializer;
+import net.minecraft.item.Item;
+import net.minecraft.registry.Registries;
+import net.minecraft.registry.Registry;
+import net.minecraft.util.Identifier;
+
+public class HornOfTheWild implements ModInitializer {
+
+    public static final String MOD_ID = "hotw";
+
+    public static final HornOfTheWildItem hornofthewild = new HornOfTheWildItem(new Item.Settings());
+
+    @Override
+    public void onInitialize() {
+        Registry.register(Registries.ITEM, new Identifier(MOD_ID, "hornofthewild"), hornofthewild);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/ovh/herisson/hornofthewild/HornOfTheWildItem.java b/src/main/java/ovh/herisson/hornofthewild/HornOfTheWildItem.java
new file mode 100644
index 0000000..4137084
--- /dev/null
+++ b/src/main/java/ovh/herisson/hornofthewild/HornOfTheWildItem.java
@@ -0,0 +1,86 @@
+package ovh.herisson.hornofthewild;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.BlockState;
+import net.minecraft.block.entity.BlockEntity;
+import net.minecraft.entity.LivingEntity;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.ItemUsage;
+import net.minecraft.registry.RegistryKeys;
+import net.minecraft.registry.tag.TagKey;
+import net.minecraft.sound.SoundCategory;
+import net.minecraft.sound.SoundEvents;
+import net.minecraft.text.Text;
+import net.minecraft.util.Hand;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.TypedActionResult;
+import net.minecraft.util.UseAction;
+import net.minecraft.util.math.BlockBox;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class HornOfTheWildItem extends Item {
+    public static final TagKey<Block> HORN_BREAKABLE = TagKey.of(RegistryKeys.BLOCK, new Identifier(HornOfTheWild.MOD_ID, "hotw_breakable"));
+    public HornOfTheWildItem(Settings settings) {
+        super(settings);
+    }
+
+    @Override
+    public int getMaxUseTime(ItemStack itemStack) {
+        return 72000;
+    }
+
+    @Override
+    public TypedActionResult<ItemStack> use(World world, PlayerEntity playerEntity, Hand hand) {
+        return ItemUsage.consumeHeldItem(world, playerEntity, hand);
+    }
+
+    @Override
+    public void usageTick(World world, LivingEntity livingEntity, ItemStack itemStack, int time) {
+        if (!world.isClient) {
+            if(time % 5 == 0){
+               HornBeat(world, itemStack, livingEntity.getBlockPos(), livingEntity);
+            }
+            world.playSound(null, livingEntity.getX(), livingEntity.getY(), livingEntity.getZ(), SoundEvents.ENTITY_HORSE_BREATHE, SoundCategory.PLAYERS, 1.0F, 1.0F);
+        }
+    }
+
+    @Override
+    public UseAction getUseAction(ItemStack itemStack) {
+        return UseAction.BOW;
+    }
+
+    private static boolean canHarvest(World world, ItemStack stack, BlockPos pos, LivingEntity livingEntity) {
+        BlockState state = world.getBlockState(pos);
+        return state.isIn(HORN_BREAKABLE);
+    }
+
+    private static void HornBeat(World world, ItemStack stack, BlockPos srcPos, LivingEntity livingEntity){
+        int range = 12;
+        int rangeY = 3;
+
+        List<BlockPos> coords = new ArrayList<>();
+        for (BlockPos pos: BlockPos.iterate(srcPos.add(-range, -rangeY, -range), srcPos.add(range, rangeY, range))){
+            if(HornOfTheWildItem.canHarvest(world, stack, pos, livingEntity)){
+                coords.add(pos.toImmutable());
+            }
+        }
+
+        Collections.shuffle(coords);
+
+        int count = Math.min(coords.size(), 32);
+        for (int i = 0; i < count; i++) {
+            BlockPos currCoords = coords.get(i);
+            BlockState state = world.getBlockState(currCoords);
+            BlockEntity be = world.getBlockEntity(currCoords);
+            world.breakBlock(currCoords, true);
+        }
+
+    }
+}
diff --git a/src/main/java/ovh/herisson/hornofthewild/client/HornofthewildClient.java b/src/main/java/ovh/herisson/hornofthewild/client/HornofthewildClient.java
new file mode 100644
index 0000000..8cb3e46
--- /dev/null
+++ b/src/main/java/ovh/herisson/hornofthewild/client/HornofthewildClient.java
@@ -0,0 +1,10 @@
+package ovh.herisson.hornofthewild.client;
+
+import net.fabricmc.api.ClientModInitializer;
+
+public class HornofthewildClient implements ClientModInitializer {
+
+    @Override
+    public void onInitializeClient() {
+    }
+}
diff --git a/src/main/resources/assets/hotw/lang/en_us.json b/src/main/resources/assets/hotw/lang/en_us.json
new file mode 100644
index 0000000..0ce851d
--- /dev/null
+++ b/src/main/resources/assets/hotw/lang/en_us.json
@@ -0,0 +1,3 @@
+{
+  "item.hotw.hornofthewild": "Horn Of The Wild"
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/hotw/models/item/hornofthewild.json b/src/main/resources/assets/hotw/models/item/hornofthewild.json
new file mode 100644
index 0000000..2c783c5
--- /dev/null
+++ b/src/main/resources/assets/hotw/models/item/hornofthewild.json
@@ -0,0 +1,6 @@
+{
+  "parent": "item/generated",
+  "textures": {
+    "layer0": "hotw:item/hornofthewild"
+  }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/hotw/textures/item/hornofthewild.png b/src/main/resources/assets/hotw/textures/item/hornofthewild.png
new file mode 100644
index 0000000..c068cb6
Binary files /dev/null and b/src/main/resources/assets/hotw/textures/item/hornofthewild.png differ
diff --git a/src/main/resources/data/hotw/recipes/hornofthewild_craft.json b/src/main/resources/data/hotw/recipes/hornofthewild_craft.json
new file mode 100644
index 0000000..62c4085
--- /dev/null
+++ b/src/main/resources/data/hotw/recipes/hornofthewild_craft.json
@@ -0,0 +1,20 @@
+{
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    " # ",
+    "#F#",
+    "## "
+  ],
+  "key": {
+    "#": {
+      "tag": "minecraft:logs"
+    },
+    "F": {
+      "item": "minecraft:fern"
+    }
+  },
+  "result": {
+    "item": "hotw:hornofthewild",
+    "count": 1
+  }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/hotw/recipes/hornofthewild_stonecutter.json b/src/main/resources/data/hotw/recipes/hornofthewild_stonecutter.json
new file mode 100644
index 0000000..59cd417
--- /dev/null
+++ b/src/main/resources/data/hotw/recipes/hornofthewild_stonecutter.json
@@ -0,0 +1,9 @@
+{
+  "type": "minecraft:stonecutting",
+  "ingredient": {
+    "item": "minecraft:goat_horn"
+  },
+  "result": "hotw:hornofthewild",
+  "count": 1,
+  "category": "misc"
+}
\ No newline at end of file
diff --git a/src/main/resources/data/hotw/tags/blocks/hotw_breakable.json b/src/main/resources/data/hotw/tags/blocks/hotw_breakable.json
new file mode 100644
index 0000000..911ac34
--- /dev/null
+++ b/src/main/resources/data/hotw/tags/blocks/hotw_breakable.json
@@ -0,0 +1,16 @@
+{
+  "replace": false,
+  "values": [
+    "#minecraft:leaves",
+    "#minecraft:crops",
+    "#minecraft:fire",
+    "#minecraft:flowers",
+
+    "minecraft:grass",
+    "minecraft:large_fern",
+
+    "minecraft:tall_seagrass",
+    "minecraft:seagrass",
+    "minecraft:kelp_plant"
+  ]
+}
\ No newline at end of file
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
new file mode 100644
index 0000000..94f0ea8
--- /dev/null
+++ b/src/main/resources/fabric.mod.json
@@ -0,0 +1,28 @@
+{
+  "schemaVersion": 1,
+  "id": "hornofthewild",
+  "version": "${version}",
+  "name": "HornOfTheWild",
+  "description": "Horn of the wild from botania",
+  "authors": [],
+  "contact": {},
+  "license": "MIT",
+  "icon": "assets/hornofthewild/icon.png",
+  "environment": "*",
+  "entrypoints": {
+    "client": [
+      "ovh.herisson.hornofthewild.client.HornofthewildClient"
+    ],
+    "main": [
+      "ovh.herisson.hornofthewild.HornOfTheWild"
+    ]
+  },
+  "mixins": [
+    "hornofthewild.mixins.json"
+  ],
+  "depends": {
+    "fabricloader": ">=${loader_version}",
+    "fabric": "*",
+    "minecraft": "${minecraft_version}"
+  }
+}
diff --git a/src/main/resources/hornofthewild.mixins.json b/src/main/resources/hornofthewild.mixins.json
new file mode 100644
index 0000000..54013bf
--- /dev/null
+++ b/src/main/resources/hornofthewild.mixins.json
@@ -0,0 +1,13 @@
+{
+  "required": true,
+  "minVersion": "0.8",
+  "package": "ovh.herisson.hornofthewild.mixin",
+  "compatibilityLevel": "JAVA_17",
+  "mixins": [
+  ],
+  "client": [
+  ],
+  "injectors": {
+    "defaultRequire": 1
+  }
+}