From ee9aa977e32b3976c0ae433db43daca492409483 Mon Sep 17 00:00:00 2001 From: Redart15 Date: Sat, 1 Nov 2025 15:57:34 +0100 Subject: [PATCH 1/2] moved all the stuff from my other commands mods to here --- gradle.properties | 6 +- .../redart15/commandly/CommandlyClient.java | 25 ++ .../java/redart15/commandly/CommandlyMod.java | 32 +++ .../redart15/commandly/CommandlyServer.java | 14 ++ .../commandly/command/CommadlyCommands.java | 20 ++ .../commandly/command/CommandGrow.java | 101 ++++++++ .../mixin/ItemToolPickaxeMixinVeinMining.java | 33 +++ .../mixin/StopGrassSpreadingMixin.java | 101 ++++++++ .../commandly/mixin/StopMossSpreading.java | 20 ++ .../java/redart15/commandly/util/Point.java | 56 +++++ .../commandly/veincapitator/OreGroups.java | 96 ++++++++ .../commandly/veincapitator/OreTags.java | 30 +++ .../veincapitator/PickAxeRegister.java | 52 ++++ .../commandly/veincapitator/VeinMining.java | 223 ++++++++++++++++++ .../turniplabs/examplemod/ExampleMod.java | 38 --- src/main/resources/commandly.mixins.json | 16 ++ src/main/resources/examplemod.mixins.json | 13 - src/main/resources/fabric.mod.json | 41 ++-- .../lang/{examplemod => commandly}/en_US.lang | 0 19 files changed, 839 insertions(+), 78 deletions(-) create mode 100644 src/main/java/redart15/commandly/CommandlyClient.java create mode 100644 src/main/java/redart15/commandly/CommandlyMod.java create mode 100644 src/main/java/redart15/commandly/CommandlyServer.java create mode 100644 src/main/java/redart15/commandly/command/CommadlyCommands.java create mode 100644 src/main/java/redart15/commandly/command/CommandGrow.java create mode 100644 src/main/java/redart15/commandly/mixin/ItemToolPickaxeMixinVeinMining.java create mode 100644 src/main/java/redart15/commandly/mixin/StopGrassSpreadingMixin.java create mode 100644 src/main/java/redart15/commandly/mixin/StopMossSpreading.java create mode 100644 src/main/java/redart15/commandly/util/Point.java create mode 100644 src/main/java/redart15/commandly/veincapitator/OreGroups.java create mode 100644 src/main/java/redart15/commandly/veincapitator/OreTags.java create mode 100644 src/main/java/redart15/commandly/veincapitator/PickAxeRegister.java create mode 100644 src/main/java/redart15/commandly/veincapitator/VeinMining.java delete mode 100644 src/main/java/turniplabs/examplemod/ExampleMod.java create mode 100644 src/main/resources/commandly.mixins.json delete mode 100644 src/main/resources/examplemod.mixins.json rename src/main/resources/lang/{examplemod => commandly}/en_US.lang (100%) diff --git a/gradle.properties b/gradle.properties index 4772356..55ed34f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,9 @@ loader_version=0.15.6-bta.7 # Other Mods mod_menu_version=3.0.0 -halplibe_version=5.2.4 +halplibe_version=5.3.1 # Mod mod_version=1.0.0 -mod_group=turniplabs -mod_name=examplemod +mod_group=redart15 +mod_name=commandly diff --git a/src/main/java/redart15/commandly/CommandlyClient.java b/src/main/java/redart15/commandly/CommandlyClient.java new file mode 100644 index 0000000..84644e8 --- /dev/null +++ b/src/main/java/redart15/commandly/CommandlyClient.java @@ -0,0 +1,25 @@ +package redart15.commandly; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import redart15.commandly.command.CommadlyCommands; +import turniplabs.halplibe.util.ClientStartEntrypoint; + +@Environment(EnvType.CLIENT) +public class CommandlyClient implements ClientModInitializer, ClientStartEntrypoint { + @Override + public void onInitializeClient() { + CommadlyCommands.registerClientCommands(); + } + + @Override + public void beforeClientStart() { + + } + + @Override + public void afterClientStart() { + + } +} diff --git a/src/main/java/redart15/commandly/CommandlyMod.java b/src/main/java/redart15/commandly/CommandlyMod.java new file mode 100644 index 0000000..97fa54a --- /dev/null +++ b/src/main/java/redart15/commandly/CommandlyMod.java @@ -0,0 +1,32 @@ +package redart15.commandly; + +import net.fabricmc.api.ModInitializer; +import net.minecraft.core.data.gamerule.GameRuleBoolean; +import net.minecraft.core.data.gamerule.GameRules; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import redart15.commandly.veincapitator.OreGroups; +import turniplabs.halplibe.util.GameStartEntrypoint; + +public class CommandlyMod implements GameStartEntrypoint, ModInitializer { + public static final String MOD_ID = "commandly"; + public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); + public static GameRuleBoolean MOSS_SPREADING = GameRules.register(new GameRuleBoolean("doMossSpreading", true)); + public static GameRuleBoolean GRASS_SPREADING = GameRules.register(new GameRuleBoolean("doGrassSpreading", true)); + public static GameRuleBoolean VEIN_MINING = GameRules.register(new GameRuleBoolean("veinmining", false)); + @Override + public void onInitialize() { + OreGroups.init(); + LOGGER.info("Commandly initialized"); + } + + @Override + public void beforeGameStart() { + + } + + @Override + public void afterGameStart() { + + } +} diff --git a/src/main/java/redart15/commandly/CommandlyServer.java b/src/main/java/redart15/commandly/CommandlyServer.java new file mode 100644 index 0000000..8d5504e --- /dev/null +++ b/src/main/java/redart15/commandly/CommandlyServer.java @@ -0,0 +1,14 @@ +package redart15.commandly; + +import net.fabricmc.api.DedicatedServerModInitializer; +import redart15.commandly.command.CommadlyCommands; + +import static redart15.commandly.CommandlyMod.LOGGER; + +public class CommandlyServer implements DedicatedServerModInitializer { + @Override + public void onInitializeServer() { + CommadlyCommands.registerServerCommands(); + LOGGER.info("Commandly server initialized."); + } +} diff --git a/src/main/java/redart15/commandly/command/CommadlyCommands.java b/src/main/java/redart15/commandly/command/CommadlyCommands.java new file mode 100644 index 0000000..3887544 --- /dev/null +++ b/src/main/java/redart15/commandly/command/CommadlyCommands.java @@ -0,0 +1,20 @@ +package redart15.commandly.command; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.core.net.command.CommandManager; + +public class CommadlyCommands { + + + @Environment(EnvType.CLIENT) + public static void registerClientCommands() { + CommandManager.registerCommand(new CommandGrow()); + } + + @Environment(EnvType.SERVER) + public static void registerServerCommands() { + CommandManager.registerServerCommand(new CommandGrow()); + } + +} diff --git a/src/main/java/redart15/commandly/command/CommandGrow.java b/src/main/java/redart15/commandly/command/CommandGrow.java new file mode 100644 index 0000000..42394f8 --- /dev/null +++ b/src/main/java/redart15/commandly/command/CommandGrow.java @@ -0,0 +1,101 @@ +package redart15.commandly.command; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.ArgumentBuilderLiteral; +import com.mojang.brigadier.context.CommandContext; +import net.minecraft.core.block.Block; +import net.minecraft.core.block.BlockLogic; +import net.minecraft.core.entity.player.Player; +import net.minecraft.core.item.IBonemealable; +import net.minecraft.core.item.ItemStack; +import net.minecraft.core.item.Items; +import net.minecraft.core.net.command.CommandManager; +import net.minecraft.core.net.command.CommandSource; +import net.minecraft.core.util.helper.Side; +import net.minecraft.core.world.World; +import net.minecraft.core.world.chunk.*; +import redart15.commandly.util.Point; + +import java.util.*; + +@SuppressWarnings("ALL") //cause this drives me nuts +public class CommandGrow implements CommandManager.CommandRegistry { + private static int worldHeight = 256; + private static byte radius = 9; + + public void register(CommandDispatcher dispatcher) { + dispatcher.register((ArgumentBuilderLiteral) ArgumentBuilderLiteral.literal("grow") + .requires(c -> ((CommandSource) c).hasAdmin()).executes(c -> { + return growCommand(c); + })); + } + + private int growCommand(CommandContext c) { + CommandSource source = (CommandSource) c.getSource(); + Player player = source.getSender(); + World world = source.getWorld(); + Set loaded = CommandGrow.getLoadedChunks(world, player.chunkCoordX, player.chunkCoordY, player.chunkCoordZ); + List bonemealTargets = getAllBonemeableBlocks(world, loaded); + grow(world, bonemealTargets); + return 1; + } + + public void grow(World world, List targets){ + Random rand = new Random(); + for(Point p : targets){ + int x = p.getIntX(); + int y = p.getIntY(); + int z = p.getIntZ(); + Block block = world.getBlock(x,y,z); + if(block == null) continue; + BlockLogic logic = block.getLogic(); + if (block.getLogic() instanceof IBonemealable) { + ((IBonemealable)logic).onBonemealUsed(new ItemStack(Items.DYE), (Player) null, world, x,y,z, Side.TOP, 0,0); + } + } + } + + public List getAllBonemeableBlocks(World world,Set loaded) { + List bonemeableBlocks = new ArrayList(); + for(ChunkCoordinate coords: loaded){ + bonemeableBlocks.addAll(getBonemeableBlocks(world, coords)); + } + return bonemeableBlocks; + } + + public List getBonemeableBlocks(World world,ChunkCoordinate chunkCoordinate) { + List bonemealableBlock = new ArrayList(); + int ix = chunkCoordinate.x * 16; + int iz = chunkCoordinate.z * 16; + for (int y = 0; y <= worldHeight; y++) { + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + int curX = ix + x; + int curZ = iz + z; + Block block = world.getBlock(curX, y, curZ); + if (block == null) continue; + if (block.id() == 0) continue; + if (block.getLogic() instanceof IBonemealable) { + bonemealableBlock.add(new Point(curX, y, curZ)); + } + } + } + } + return bonemealableBlock; + } + + public static Set getLoadedChunks(World world,int playerChunkX, int playerChunkY, int playerChunkZ) { + Set loadedChunks = new HashSet(); + for (int x = -radius; x <= radius; ++x) { + for (int z = -radius; z <= radius; ++z) { + int chunkCoordX = x + playerChunkX; + int chunkCoordZ = z + playerChunkZ; + if (world.isChunkLoaded(chunkCoordX, chunkCoordZ)) { + loadedChunks.add(new ChunkCoordinate(chunkCoordX, chunkCoordZ)); + } + } + } + return loadedChunks; + } +} + diff --git a/src/main/java/redart15/commandly/mixin/ItemToolPickaxeMixinVeinMining.java b/src/main/java/redart15/commandly/mixin/ItemToolPickaxeMixinVeinMining.java new file mode 100644 index 0000000..fcb8dd8 --- /dev/null +++ b/src/main/java/redart15/commandly/mixin/ItemToolPickaxeMixinVeinMining.java @@ -0,0 +1,33 @@ +package redart15.commandly.mixin; + +import net.minecraft.core.block.Block; +import net.minecraft.core.data.tag.Tag; +import net.minecraft.core.entity.player.Player; +import net.minecraft.core.item.ItemStack; +import net.minecraft.core.item.material.ToolMaterial; +import net.minecraft.core.item.tool.ItemTool; +import net.minecraft.core.item.tool.ItemToolPickaxe; +import net.minecraft.core.util.helper.Side; +import net.minecraft.core.world.World; +import org.spongepowered.asm.mixin.Mixin; +import redart15.commandly.CommandlyMod; +import redart15.commandly.veincapitator.VeinMining; + +@Mixin(value = ItemToolPickaxe.class, remap = false) +public class ItemToolPickaxeMixinVeinMining extends ItemTool { + + protected ItemToolPickaxeMixinVeinMining(String name, String namespaceId, int id, int damageDealt, ToolMaterial toolMaterial, Tag> tagEffectiveAgainst) { + super(name, namespaceId, id, damageDealt, toolMaterial, tagEffectiveAgainst); + } + + @Override + public boolean beforeDestroyBlock(World world, ItemStack itemStack, int blockId, int x, int y, int z, Side side, Player player) { + if (world.getGameRuleValue(CommandlyMod.VEIN_MINING) + && !player.isSneaking() + && !world.isClientSide + ) { + return VeinMining.veinMining(world, itemStack, x, y, z, player).mine(blockId, side); + } + return true; + } +} diff --git a/src/main/java/redart15/commandly/mixin/StopGrassSpreadingMixin.java b/src/main/java/redart15/commandly/mixin/StopGrassSpreadingMixin.java new file mode 100644 index 0000000..a86c807 --- /dev/null +++ b/src/main/java/redart15/commandly/mixin/StopGrassSpreadingMixin.java @@ -0,0 +1,101 @@ +package redart15.commandly.mixin; + +import net.minecraft.core.block.Block; +import net.minecraft.core.block.BlockLogicGrass; +import net.minecraft.core.block.Blocks; +import net.minecraft.core.data.gamerule.GameRules; +import net.minecraft.core.world.World; +import net.minecraft.core.world.biome.Biome; +import net.minecraft.core.world.biome.Biomes; +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 redart15.commandly.CommandlyMod; + +import java.util.Random; +@Mixin(value = BlockLogicGrass.class, remap = false) +public abstract class StopGrassSpreadingMixin{ + + @Inject(method = "updateTick", at = @At("HEAD"), cancellable = true) + public void updateTick(World world, int x, int y, int z, Random rand, CallbackInfo ci) { + + if (world.isClientSide) { + return; + } + + BlockLogicGrass self = (BlockLogicGrass)(Object)this; + + Block dirt = self.dirt; + Block block = self.block; + + if (revertToDirt(world, x, y, z, rand, dirt)) return; + if (world.getBlockLightValue(x, y + 1, z) < 9) { + return; + } + spreadGrass(world, x, y, z, rand, dirt, block); + spreadsFlowers(world, x, y, z, rand); + ci.cancel(); + } + + private void spreadGrass(World world, int x, int y, int z, Random rand, Block dirt, Block block) { + if(!world.getGameRuleValue(CommandlyMod.GRASS_SPREADING)) { + return; + } + for(int i = 0; i < 4; ++i) { + int x1 = x + rand.nextInt(3) - 1; + int y1 = y + rand.nextInt(5) - 3; + int z1 = z + rand.nextInt(3) - 1; + if (world.getBlockId(x1, y1, z1) == dirt.id() && world.getBlockLightValue(x1, y1 + 1, z1) >= 4 && Blocks.lightBlock[world.getBlockId(x1, y1 + 1, z1)] <= 2) { + world.setBlockWithNotify(x1, y1, z1, block.id()); + } + } + } + + private boolean revertToDirt(World world, int x, int y, int z, Random rand, Block dirt) { + if (world.getBlockLightValue(x, y + 1, z) < 4 && Blocks.lightBlock[world.getBlockId(x, y + 1, z)] > 2) { + if (rand.nextInt(4) == 0) { + world.setBlockWithNotify(x, y, z, dirt.id()); + } + return true; + } + return false; + } + + private void spreadsFlowers(World world, int x, int y, int z, Random rand) { + if (!((Boolean) world.getGameRuleValue(GameRules.DO_SEASONAL_GROWTH)) + || world.getBlockId(x, y + 1, z) != 0 + || world.getSeasonManager().getCurrentSeason() == null + || !world.getSeasonManager().getCurrentSeason().growFlowers + || rand.nextInt(256) != 0 + ) return; + int flowerID = determineFlower(world,x,y,z,rand); + world.setBlockWithNotify(x, y + 1, z, flowerID); + } + + private int determineFlower(World world, int x,int y, int z, Random rand){ + int r = rand.nextInt(400); + if (r < 26) { + return Blocks.FLOWER_RED.id(); + } + if (r < 41) { + return Blocks.FLOWER_YELLOW.id(); + } + if (r < 60) { + Biome biome = world.getBlockBiome(x, y + 1, z); + if (biome == Biomes.OVERWORLD_BIRCH_FOREST || biome == Biomes.OVERWORLD_SEASONAL_FOREST) { + return Blocks.FLOWER_PINK.id(); + } + if (biome == Biomes.OVERWORLD_MEADOW || biome == Biomes.OVERWORLD_BOREAL_FOREST || biome == Biomes.OVERWORLD_SHRUBLAND) { + return Blocks.FLOWER_PURPLE.id(); + } + if (biome == Biomes.OVERWORLD_FOREST || biome == Biomes.OVERWORLD_SWAMPLAND || biome == Biomes.OVERWORLD_RAINFOREST || biome == Biomes.OVERWORLD_CAATINGA) { + return Blocks.FLOWER_LIGHT_BLUE.id(); + } + } + if (rand.nextInt(8) == 0) { + return Blocks.TALLGRASS_FERN.id(); + } + return Blocks.TALLGRASS.id(); + } +} diff --git a/src/main/java/redart15/commandly/mixin/StopMossSpreading.java b/src/main/java/redart15/commandly/mixin/StopMossSpreading.java new file mode 100644 index 0000000..7cdae40 --- /dev/null +++ b/src/main/java/redart15/commandly/mixin/StopMossSpreading.java @@ -0,0 +1,20 @@ +package redart15.commandly.mixin; + +import net.minecraft.core.block.BlockLogicMoss; +import net.minecraft.core.world.World; +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.CallbackInfoReturnable; +import redart15.commandly.CommandlyMod; + +@Mixin(value = BlockLogicMoss.class, remap = false) +public class StopMossSpreading { + + @Inject(method = "canMossSpread(Lnet/minecraft/core/world/World;III)Z", at=@At("HEAD"), cancellable = true) + public void allowedMossSpread(World world, int x, int y, int z, CallbackInfoReturnable cir){ + if(!world.isClientSide && !world.getGameRuleValue(CommandlyMod.MOSS_SPREADING)){ + cir.setReturnValue(false); + } + } +} diff --git a/src/main/java/redart15/commandly/util/Point.java b/src/main/java/redart15/commandly/util/Point.java new file mode 100644 index 0000000..3a29629 --- /dev/null +++ b/src/main/java/redart15/commandly/util/Point.java @@ -0,0 +1,56 @@ +package redart15.commandly.util; + +import java.util.Objects; + +public class Point { + private float x,y,z; + + public Point(int x, int y, int z){ + this.x = x; + this.y = y; + this.z = z; + } + + public Point(float x, float y, float z){ + this.x = x; + this.y = y; + this.z = z; + } + + public static int intDistance(Point p, Point q){ + return (int)Math.ceil(floatDistance(p,q)); + } + + public static float floatDistance(Point p, Point q){ + float dx = p.getFloatX() - q.getFloatX(); + float dy = p.getFloatY() - q.getFloatY(); + float dz = p.getFloatZ() - q.getFloatZ(); + return (float)(Math.sqrt(dx * dx + dy * dy + dz * dz)); + } + + @Override + public int hashCode() { + return Objects.hash(x,y,z); + } + + @Override + public boolean equals(Object obj){ + if(obj == null) return false; + if(obj instanceof Point) return false; + Point that = (Point)obj; + return Float.compare(this.x, that.getFloatX()) == 0 + && Float.compare(this.y, that.getFloatY()) == 0 + && Float.compare(this.z, that.getFloatZ()) == 0; + } + + // a bunch of boilerplate + public int getIntX() {return (int)Math.ceil(x);} + public int getIntY() {return (int)Math.ceil(y);} + public int getIntZ() {return (int)Math.ceil(z);} + public float getFloatX() {return x;} + public float getFloatY() {return y;} + public float getFloatZ() {return z;} + public void setX(float x) { this.x = x;} + public void setY(float y) { this.y = y;} + public void setZ(float z) { this.z = z;} +} diff --git a/src/main/java/redart15/commandly/veincapitator/OreGroups.java b/src/main/java/redart15/commandly/veincapitator/OreGroups.java new file mode 100644 index 0000000..d71f5b4 --- /dev/null +++ b/src/main/java/redart15/commandly/veincapitator/OreGroups.java @@ -0,0 +1,96 @@ +package redart15.commandly.veincapitator; + +import net.minecraft.core.block.Block; +import net.minecraft.core.block.Blocks; +import net.minecraft.core.util.collection.NamespaceID; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +/// Ore -> Group -> List of Group members +public class OreGroups { + public static final OreGroups instance = new OreGroups(); + public Map> GROUP_TO_BLOCKS = new HashMap<>(); + public Map BLOCKS_TO_GROUP = new HashMap<>(); + + public static void init(){} + + protected OreGroups() { + this.register(); + } + + private void register() { + this.addOreGroups("coal", Blocks.ORE_COAL_BASALT); + this.addOreGroups("coal", Blocks.ORE_COAL_GRANITE); + this.addOreGroups("coal", Blocks.ORE_COAL_LIMESTONE); + this.addOreGroups("coal", Blocks.ORE_COAL_STONE); + this.addOreGroups("coal", Blocks.ORE_COAL_PERMAFROST); + + this.addOreGroups("diamond", Blocks.ORE_DIAMOND_STONE); + this.addOreGroups("diamond",Blocks.ORE_DIAMOND_BASALT); + this.addOreGroups("diamond",Blocks.ORE_DIAMOND_GRANITE); + this.addOreGroups("diamond",Blocks.ORE_DIAMOND_LIMESTONE); + this.addOreGroups("diamond", Blocks.ORE_DIAMOND_PERMAFROST); + + this.addOreGroups("gold",Blocks.ORE_GOLD_STONE); + this.addOreGroups("gold",Blocks.ORE_GOLD_BASALT); + this.addOreGroups("gold",Blocks.ORE_GOLD_GRANITE); + this.addOreGroups("gold",Blocks.ORE_GOLD_LIMESTONE); + this.addOreGroups("gold", Blocks.ORE_GOLD_PERMAFROST); + + this.addOreGroups("iron",Blocks.ORE_IRON_STONE); + this.addOreGroups("iron",Blocks.ORE_IRON_BASALT); + this.addOreGroups("iron",Blocks.ORE_IRON_GRANITE); + this.addOreGroups("iron",Blocks.ORE_IRON_LIMESTONE); + this.addOreGroups("iron",Blocks.ORE_IRON_PERMAFROST); + + this.addOreGroups("nether_coal",Blocks.ORE_NETHERCOAL_NETHERRACK); + + this.addOreGroups("lapis",Blocks.ORE_LAPIS_STONE); + this.addOreGroups("lapis",Blocks.ORE_LAPIS_BASALT); + this.addOreGroups("lapis",Blocks.ORE_LAPIS_GRANITE); + this.addOreGroups("lapis",Blocks.ORE_LAPIS_LIMESTONE); + this.addOreGroups("lapis",Blocks.ORE_LAPIS_PERMAFROST); + + this.addOreGroups("redstone",Blocks.ORE_REDSTONE_STONE); + this.addOreGroups("redstone",Blocks.ORE_REDSTONE_BASALT); + this.addOreGroups("redstone",Blocks.ORE_REDSTONE_GRANITE); + this.addOreGroups("redstone",Blocks.ORE_REDSTONE_LIMESTONE); + this.addOreGroups("redstone",Blocks.ORE_REDSTONE_PERMAFROST); + + this.addOreGroups("redstone",Blocks.ORE_REDSTONE_GLOWING_STONE); + this.addOreGroups("redstone",Blocks.ORE_REDSTONE_GLOWING_BASALT); + this.addOreGroups("redstone",Blocks.ORE_REDSTONE_GLOWING_GRANITE); + this.addOreGroups("redstone",Blocks.ORE_REDSTONE_GLOWING_LIMESTONE); + this.addOreGroups("redstone",Blocks.ORE_REDSTONE_GLOWING_PERMAFROST); + } + + public boolean addOreGroups(String groupName, Block block) { + HashSet group_to_block_set = this.GROUP_TO_BLOCKS.computeIfAbsent(groupName, key -> new HashSet<>()); + if(!group_to_block_set.add(block.namespaceId())) return false; + this.BLOCKS_TO_GROUP.put(block.namespaceId(), groupName); + block.withTags(OreTags.ORE); + return true; + } + + public String getOreGroupName(Block block){ + return this.BLOCKS_TO_GROUP.getOrDefault(block.namespaceId(), ""); + } + + public HashSet getOreGroup(String name){ + return this.GROUP_TO_BLOCKS.getOrDefault(name, new HashSet<>()); + } + + public HashSet getOreGroupFromMember(Block block){ + return getOreGroup(getOreGroupName(block)); + } + + public Map> getGROUP_TO_BLOCKS(){ + return this.GROUP_TO_BLOCKS; + } + + public Map getBLOCKS_TO_GROUP(){ + return this.BLOCKS_TO_GROUP; + } +} diff --git a/src/main/java/redart15/commandly/veincapitator/OreTags.java b/src/main/java/redart15/commandly/veincapitator/OreTags.java new file mode 100644 index 0000000..bde904f --- /dev/null +++ b/src/main/java/redart15/commandly/veincapitator/OreTags.java @@ -0,0 +1,30 @@ +package redart15.commandly.veincapitator; + +import net.minecraft.core.block.Block; +import net.minecraft.core.block.tag.BlockTags; +import net.minecraft.core.data.tag.Tag; + +import java.lang.reflect.Field; + +import static net.minecraft.core.block.tag.BlockTags.TAG_LIST; +import static org.apache.log4j.builders.appender.SocketAppenderBuilder.LOGGER; + +public class OreTags { + public static Tag> ORE = Tag.of("ore"); + + public static void init(){} + + static { + Field[] declaredFields = BlockTags.class.getDeclaredFields(); + for (Field field : declaredFields) { + if (!field.getType().equals(Tag.class)) { + continue; + } + try { + TAG_LIST.add((Tag) field.get(null)); + } catch (Exception exception) { + LOGGER.error("Failed to add tag '{}'!", field.getName(), exception); + } + } + } +} diff --git a/src/main/java/redart15/commandly/veincapitator/PickAxeRegister.java b/src/main/java/redart15/commandly/veincapitator/PickAxeRegister.java new file mode 100644 index 0000000..2d8c2d7 --- /dev/null +++ b/src/main/java/redart15/commandly/veincapitator/PickAxeRegister.java @@ -0,0 +1,52 @@ +package redart15.commandly.veincapitator; + +import net.minecraft.core.item.Item; +import net.minecraft.core.item.material.ToolMaterial; +import net.minecraft.core.item.tool.ItemTool; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +public class PickAxeRegister { + protected static final Map toolSet = new HashMap(); + + + public static boolean containsID(int id) { + return toolSet.containsKey(id); + } + + public static boolean addPickaxe(Item pickaxe) { + try { + Method method = pickaxe.getClass().getMethod("getMaterial"); + ToolMaterial toolMaterial = (ToolMaterial) method.invoke(pickaxe); + toolSet.put(pickaxe.id, toolMaterial); + return true; + } catch (NoSuchMethodException e) { + return false; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public static ToolMaterial getMaterial(Item item){ + if(item instanceof ItemTool){ + return ((ItemTool) item).getMaterial(); + } + return PickAxeRegister.getMaterial(item.id); + } + + private static ToolMaterial getMaterial(int id){ + return toolSet.getOrDefault(id, ToolMaterial.wood); + } + + public static int getMiningLevel(Item item){ + return PickAxeRegister.getMaterial(item).getMiningLevel(); + } + + private static int getMiningLevel(int id){ + return PickAxeRegister.getMaterial(id).getMiningLevel(); + } + +} diff --git a/src/main/java/redart15/commandly/veincapitator/VeinMining.java b/src/main/java/redart15/commandly/veincapitator/VeinMining.java new file mode 100644 index 0000000..44eaac6 --- /dev/null +++ b/src/main/java/redart15/commandly/veincapitator/VeinMining.java @@ -0,0 +1,223 @@ +package redart15.commandly.veincapitator; + +import net.minecraft.core.block.Block; +import net.minecraft.core.block.BlockLogic; +import net.minecraft.core.block.Blocks; +import net.minecraft.core.block.entity.TileEntity; +import net.minecraft.core.block.tag.BlockTags; +import net.minecraft.core.entity.EntityItem; +import net.minecraft.core.entity.player.Player; +import net.minecraft.core.enums.EnumDropCause; +import net.minecraft.core.item.Item; +import net.minecraft.core.item.ItemStack; +import net.minecraft.core.item.material.ToolMaterial; +import net.minecraft.core.item.tool.ItemToolPickaxe; +import net.minecraft.core.util.collection.NamespaceID; +import net.minecraft.core.util.helper.Side; +import net.minecraft.core.world.World; +import net.minecraft.core.world.chunk.ChunkPosition; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.*; + +import static redart15.commandly.veincapitator.OreTags.ORE; + +public class VeinMining { + private static final int MAX_VEIN_SIZE = 64; + private final World world; + private final ItemStack tool; + private final ChunkPosition point; + private final Player player; + private HashSet miningGroup; + private boolean onlyThisID = false; + + + public VeinMining(World world, ItemStack itemStack, int x, int y, int z, Player player) { + this.world = world; + this.tool = itemStack; + this.point = new ChunkPosition(x, y, z); + this.player = player; + } + + public static VeinMining veinMining(World world, ItemStack itemStack, int x, int y, int z, Player player) { + return new VeinMining(world, itemStack, x, y, z, player); + } + + + public boolean mine(int blockId, Side side) { + Block block = Blocks.getBlock(blockId); + if (block == null || !this.canBeVeinMined(block)) { + return false; + } + this.miningGroup = this.getGroup(block); + boolean itemStackDamageable = tool.isItemStackDamageable(); + + ToolMaterial material = PickAxeRegister.getMaterial(tool.getItem()); + EnumDropCause dropCause = material.isSilkTouch() ? EnumDropCause.SILK_TOUCH : EnumDropCause.PROPER_TOOL; + + int veinSize = MAX_VEIN_SIZE; + if (itemStackDamageable) { + int durabilityLeft = tool.getMaxDamage() - tool.getMetadata(); + veinSize = Math.min(durabilityLeft, MAX_VEIN_SIZE); + } + + Set toBeMined = this.findAllOreBlocks(veinSize); + + for (ChunkPosition pos : toBeMined) { + if (!this.breakBlock(pos, dropCause)) continue; + if (itemStackDamageable) { + tool.damageItem(1, player); + if (tool.stackSize <= 0) { + this.player.destroyCurrentEquippedItem(); + } + } + } + return true; + } + + private boolean canBeVeinMined(Block block) { + Block theBlock = world.getBlock(point.x, point.y, point.z); + if (theBlock == null || theBlock.id() != block.id()) { + return false; + } + if (!block.hasTag(BlockTags.MINEABLE_BY_PICKAXE)) { + return false; + } + + if (this.tool == null) { + return false; + } + Item toolItem = this.tool.getItem(); + if (!(toolItem instanceof ItemToolPickaxe) && !PickAxeRegister.containsID(toolItem.id)) return false; + + int toolMiningLevel = PickAxeRegister.getMiningLevel(toolItem); + int blockMiningLevel = ItemToolPickaxe.miningLevels.getOrDefault(block, 0); + if (blockMiningLevel > toolMiningLevel) return false; + + return block.hasTag(ORE) || this.languageKeyOre(block); + } + + private boolean languageKeyOre(Block block) { + String language_key = block.getLanguageKey(0); + String[] substrings = language_key.split("\\."); + for (String str : substrings) { + if (str.equalsIgnoreCase("ore")) { + this.onlyThisID = true; + return true; + } + } + return false; + } + + private HashSet getGroup(Block block) { + if (onlyThisID) { + this.onlyThisID = false; + HashSet set = new HashSet<>(); + set.add(block.namespaceId()); + return set; + } + return OreGroups.instance.getOreGroupFromMember(block); + } + + private Set findAllOreBlocks(int veinSize) { + Queue queue = new ArrayDeque<>(); + Set visited = new LinkedHashSet<>(); + + queue.add(this.point); + visited.add(this.point); + + int radius = 1; + while (!queue.isEmpty() && veinSize > 0) { + ChunkPosition from = queue.poll(); + for (int offX = -radius; offX <= radius; offX++) { + for (int offY = -radius; offY <= radius; offY++) { + for (int offZ = -radius; offZ <= radius; offZ++) { + if ((offX == 0 && offZ == 0 && offY == 0)) continue; + ChunkPosition to = new ChunkPosition(from.x + offX, from.y + offY, from.z + offZ); + if (visited.contains(to)) continue; + Block nextBlock = this.world.getBlock(to.x, to.y, to.z); + if (nextBlock == null || !this.miningGroup.contains(nextBlock.namespaceId())) continue; + visited.add(to); + queue.add(to); + veinSize--; + if (veinSize <= 0) { + return visited; + } + } + } + } + } + return visited; + } + + private boolean breakBlock(ChunkPosition pos, EnumDropCause dropCause) { + Block block = this.world.getBlock(pos.x, pos.y, pos.z); + int meta = this.world.getBlockMetadata(pos.x, pos.y, pos.z); + if (block == null) { + return false; + } + if (!this.world.setBlockWithNotify(pos.x, pos.y, pos.z, 0)) { + return false; + } + if(player.getGamemode().dropBlockOnBreak()){ + ItemStack[] drops = this.getBreakResult(block, this.world, dropCause, pos.x, pos.y, pos.z, meta, (TileEntity) null); + if (EntityItem.enableItemClumping) { + + } else { + this.dropItems(drops, pos); + } + } + this.world.playBlockEvent(this.player, 2001, pos.x, pos.y, pos.z, block.id()); + return true; + + } + + protected void dropItems(ItemStack[] items, ChunkPosition pos) { + if (items == null) { + return; + } + for (int i = 0; i < items.length; i++) { + ItemStack stack = items[i]; + while (stack.stackSize > 0) { + this.world.dropItem(pos.x, pos.y, pos.z, stack.splitStack(1)); + } + } + + } + + + private ItemStack[] getBreakResult(@NotNull Block block, World world, EnumDropCause dropCause, int x, int y, int z, int meta, TileEntity tileEntity) { + ItemStack[] result = block.getBreakResult(world, dropCause, x, y, z, meta, tileEntity); + if (!this.canGetAdditionalBreakResults(block, tool.getItem(), meta)) { + return result; + } + return this.getAdditionalBreakResult(world, result, meta, block); + } + + private boolean canGetAdditionalBreakResults(Block block, Item tool, int meta) { + try { + BlockLogic logic = block.getLogic(); + Method method = logic.getClass().getMethod("canGetAdditionalBreakResult", Item.class, Integer.class); + return (Boolean) method.invoke(logic, tool, meta); + } catch (NoSuchMethodException e) { + return false; + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + private ItemStack[] getAdditionalBreakResult(World world, ItemStack[] result, int meta, Block block) { + try { + BlockLogic logic = block.getLogic(); + Method method = logic.getClass().getMethod("getAdditionalBreakResult", World.class, Item.class, ItemStack[].class, Integer.class); + return (ItemStack[]) method.invoke(logic, world, tool.getItem(), result, meta); + } catch (NoSuchMethodException e) { + return result; + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/turniplabs/examplemod/ExampleMod.java b/src/main/java/turniplabs/examplemod/ExampleMod.java deleted file mode 100644 index 7ec2a41..0000000 --- a/src/main/java/turniplabs/examplemod/ExampleMod.java +++ /dev/null @@ -1,38 +0,0 @@ -package turniplabs.examplemod; - -import net.fabricmc.api.ModInitializer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import turniplabs.halplibe.util.ClientStartEntrypoint; -import turniplabs.halplibe.util.GameStartEntrypoint; -import turniplabs.halplibe.util.RecipeEntrypoint; - - -public class ExampleMod implements ModInitializer, RecipeEntrypoint, GameStartEntrypoint { - public static final String MOD_ID = "examplemod"; - public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); - @Override - public void onInitialize() { - LOGGER.info("ExampleMod initialized."); - } - - @Override - public void onRecipesReady() { - - } - - @Override - public void initNamespaces() { - - } - - @Override - public void beforeGameStart() { - - } - - @Override - public void afterGameStart() { - - } -} diff --git a/src/main/resources/commandly.mixins.json b/src/main/resources/commandly.mixins.json new file mode 100644 index 0000000..7e3c8bb --- /dev/null +++ b/src/main/resources/commandly.mixins.json @@ -0,0 +1,16 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "redart15.commandly.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "ItemToolPickaxeMixinVeinMining", + "StopGrassSpreadingMixin", + "StopMossSpreading" + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/examplemod.mixins.json b/src/main/resources/examplemod.mixins.json deleted file mode 100644 index e98223c..0000000 --- a/src/main/resources/examplemod.mixins.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "turniplabs.examplemod.mixin", - "compatibilityLevel": "JAVA_8", - "mixins": [ - ], - "client": [ - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 94476ee..1191226 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,16 +1,15 @@ { "schemaVersion": 1, - "id": "examplemod", + "id": "commandly", "version": "${version}", - - "name": "Example Mod", - "description": "This mod aims to help new BTA modders.", + "name": "Commandly", + "description": "This mod is a port of Single Player Commands", "authors": [ - "Turnip Labs" + "Redart15" ], "contact": { "homepage": "", - "sources": "" + "sources": "https://github.com/Redart15/Commandly" }, "icon": "icon.png", @@ -18,27 +17,21 @@ "environment": "*", "entrypoints": { - "main": [ - "turniplabs.examplemod.ExampleMod" - ], - "beforeGameStart": [ - "turniplabs.examplemod.ExampleMod" - ], - "afterGameStart": [ - "turniplabs.examplemod.ExampleMod" - ], - "recipesReady": [ - "turniplabs.examplemod.ExampleMod" - ] + "main": ["redart15.commandly.CommandlyMod"], + "beforeGameStart": ["redart15.commandly.CommandlyMod"], + "afterGameStart": ["redart15.commandly.CommandlyMod"], + "recipesReady": ["redart15.commandly.CommandlyMod"], + "beforeClientStart": ["redart15.commandly.CommandlyClient"], + "afterClientStart": ["redart15.commandly.CommandlyClient"], + "server": ["redart15.commandly.CommandlyServer"] }, "mixins": [ - "examplemod.mixins.json" + "commandly.mixins.json" ], "depends": { - "minecraft": "*", - "fabricloader": ">=0.15.5" - }, - "suggests": { - } + "fabricloader": ">=0.15.5", + "halplibe": ">=5.3.1" + }, + "suggests": {} } diff --git a/src/main/resources/lang/examplemod/en_US.lang b/src/main/resources/lang/commandly/en_US.lang similarity index 100% rename from src/main/resources/lang/examplemod/en_US.lang rename to src/main/resources/lang/commandly/en_US.lang From bfeae96d3606199a56b28f5d5e335345a46bed40 Mon Sep 17 00:00:00 2001 From: Redart15 Date: Sat, 1 Nov 2025 16:05:26 +0100 Subject: [PATCH 2/2] fixed some wrong entry point implementations --- src/main/java/redart15/commandly/CommandlyMod.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/redart15/commandly/CommandlyMod.java b/src/main/java/redart15/commandly/CommandlyMod.java index 97fa54a..0b1421d 100644 --- a/src/main/java/redart15/commandly/CommandlyMod.java +++ b/src/main/java/redart15/commandly/CommandlyMod.java @@ -7,8 +7,9 @@ import org.slf4j.LoggerFactory; import redart15.commandly.veincapitator.OreGroups; import turniplabs.halplibe.util.GameStartEntrypoint; +import turniplabs.halplibe.util.RecipeEntrypoint; -public class CommandlyMod implements GameStartEntrypoint, ModInitializer { +public class CommandlyMod implements ModInitializer, RecipeEntrypoint, GameStartEntrypoint{ public static final String MOD_ID = "commandly"; public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); public static GameRuleBoolean MOSS_SPREADING = GameRules.register(new GameRuleBoolean("doMossSpreading", true)); @@ -29,4 +30,14 @@ public void beforeGameStart() { public void afterGameStart() { } + + @Override + public void onRecipesReady() { + + } + + @Override + public void initNamespaces() { + + } }