diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/PlayerAccess.java b/src/main/java/com/github/zly2006/carpetslsaddition/PlayerAccess.java new file mode 100644 index 0000000..4bdcd1d --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/PlayerAccess.java @@ -0,0 +1,5 @@ +package com.github.zly2006.carpetslsaddition; + +public interface PlayerAccess { + boolean holdingObsidianPickaxe(); +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java b/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java index 7f889bb..801205c 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java @@ -2,31 +2,33 @@ package com.github.zly2006.carpetslsaddition; import carpet.CarpetExtension; import carpet.CarpetServer; -import carpet.api.settings.*; -import com.google.common.collect.MapMaker; +import carpet.api.settings.SettingsManager; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.JsonObject; import com.mojang.brigadier.CommandDispatcher; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.Version; import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.recipe.Ingredient; +import net.minecraft.recipe.ShapedRecipe; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.injection.struct.InjectorGroupInfo; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; +import net.minecraft.util.collection.DefaultedList; import java.io.IOException; import java.io.InputStream; -import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; - -import static net.minecraft.server.command.CommandManager.*; public class ServerMain implements ModInitializer, CarpetExtension { public static final String MOD_ID = "carpet-sls-addition"; @@ -36,6 +38,8 @@ public class ServerMain implements ModInitializer, CarpetExtension { public static final Version MOD_VERSION = FabricLoader.getInstance().getModContainer(MOD_ID).get().getMetadata().getVersion(); public static ServerMain INSTANCE; MinecraftServer server; + public static final String ITEM_NAME = "item_name"; + public static final String OBSIDIAN_PICKAXE = "obsidian_pickaxe"; @Override public void onInitialize() { @@ -47,6 +51,19 @@ public class ServerMain implements ModInitializer, CarpetExtension { public void onServerLoaded(MinecraftServer server) { this.server = server; CarpetServer.settingsManager.parseSettingsClass(SLSCarpetSettings.class); + ((SettingsManagerAccessor) CarpetServer.settingsManager).loadSettings(); + if (false) { + ItemStack stack = new ItemStack(Items.STONE_PICKAXE); + stack.setCustomName(Text.empty().formatted(Formatting.LIGHT_PURPLE).append("黑曜石镐")); + stack.getOrCreateSubNbt(MOD_ID).putString(ITEM_NAME, OBSIDIAN_PICKAXE); + DefaultedList ingredients = DefaultedList.ofSize(9, Ingredient.EMPTY); + ingredients.set(0, Ingredient.ofItems(Items.OBSIDIAN)); + ingredients.set(1, Ingredient.ofItems(Items.OBSIDIAN)); + ingredients.set(2, Ingredient.ofItems(Items.OBSIDIAN)); + ingredients.set(4, Ingredient.ofItems(Items.STICK)); + ingredients.set(7, Ingredient.ofItems(Items.STICK)); + server.getRecipeManager().setRecipes(List.of(new ShapedRecipe(new Identifier(MOD_ID, "recipe.obsidian_pickaxe"), MOD_ID, 3, 3, ingredients, stack))); + } } @Override @@ -78,5 +95,17 @@ public class ServerMain implements ModInitializer, CarpetExtension { @Override public void registerCommands(CommandDispatcher dispatcher, CommandRegistryAccess commandBuildContext) { + dispatcher.register(CommandManager.literal("hat") + .requires(ServerCommandSource::isExecutedByPlayer) + .executes(context -> { + ServerPlayerEntity player = context.getSource().getPlayer(); + assert player != null; + ItemStack stack = player.getMainHandStack(); + ItemStack head = player.getEquippedStack(EquipmentSlot.HEAD); + player.equipStack(EquipmentSlot.HEAD, stack); + player.getInventory().setStack(player.getInventory().selectedSlot, head); + player.currentScreenHandler.syncState(); + return 1; + })); } } diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/SettingsManagerAccessor.java b/src/main/java/com/github/zly2006/carpetslsaddition/SettingsManagerAccessor.java new file mode 100644 index 0000000..6cf21b0 --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/SettingsManagerAccessor.java @@ -0,0 +1,5 @@ +package com.github.zly2006.carpetslsaddition; + +public interface SettingsManagerAccessor { + void loadSettings(); +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinBlock.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinBlock.java new file mode 100644 index 0000000..9b755a3 --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinBlock.java @@ -0,0 +1,33 @@ +package com.github.zly2006.carpetslsaddition.mixin; + +import carpet.patches.EntityPlayerMPFake; +import com.github.zly2006.carpetslsaddition.PlayerAccess; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import org.jetbrains.annotations.Nullable; +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 java.util.List; + +@Mixin(Block.class) +public class MixinBlock { + @Inject(method = "getDroppedStacks(Lnet/minecraft/block/BlockState;Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/entity/BlockEntity;Lnet/minecraft/entity/Entity;Lnet/minecraft/item/ItemStack;)Ljava/util/List;", at = @At("HEAD"), cancellable = true) + private static void onDrop(BlockState state, ServerWorld world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack stack, CallbackInfoReturnable> cir) { + if (entity instanceof ServerPlayerEntity player) { + if (((PlayerAccess) player).holdingObsidianPickaxe() && state.getBlock() == Blocks.OBSIDIAN) { + cir.setReturnValue(List.of(new ItemStack(Items.OBSIDIAN))); + } + } + } +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinItem.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinItem.java new file mode 100644 index 0000000..ff012eb --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinItem.java @@ -0,0 +1,24 @@ +package com.github.zly2006.carpetslsaddition.mixin; + +import com.github.zly2006.carpetslsaddition.PlayerAccess; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.util.math.BlockPos; +import net.minecraft.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; + +@Mixin(Item.class) +public class MixinItem { + @Inject(method = "canMine", at = @At("HEAD"), cancellable = true) + private void onCheckMine(BlockState state, World world, BlockPos pos, PlayerEntity miner, CallbackInfoReturnable cir) { + if (((PlayerAccess) miner).holdingObsidianPickaxe() && state.getBlock() == Blocks.OBSIDIAN) { + cir.setReturnValue(true); + } + } +} + diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinPlayerEntity.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinPlayerEntity.java new file mode 100644 index 0000000..015986c --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinPlayerEntity.java @@ -0,0 +1,46 @@ +package com.github.zly2006.carpetslsaddition.mixin; + +import com.github.zly2006.carpetslsaddition.PlayerAccess; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.GameMode; +import net.minecraft.world.World; +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.CallbackInfoReturnable; + +import static com.github.zly2006.carpetslsaddition.ServerMain.*; + +@Mixin(PlayerEntity.class) +public abstract class MixinPlayerEntity implements PlayerAccess { + @Shadow public abstract ItemStack getEquippedStack(EquipmentSlot slot); + + @Override + public boolean holdingObsidianPickaxe() { + ItemStack itemStack = getEquippedStack(EquipmentSlot.MAINHAND); + NbtCompound compound = itemStack.getSubNbt(MOD_ID); + return compound != null && compound.contains(ITEM_NAME) && compound.getString(ITEM_NAME).equals(OBSIDIAN_PICKAXE); + } + + @Inject(method = "getBlockBreakingSpeed", at = @At("HEAD"), cancellable = true) + private void onGetBlockBreakingSpeed(BlockState block, CallbackInfoReturnable cir) { + if (holdingObsidianPickaxe() && block.isOf(Blocks.OBSIDIAN)) { + cir.setReturnValue(750f);// f = speed / 1500 + } + } + + @Inject(method = "canHarvest", at = @At("HEAD"), cancellable = true) + private void onGetCanMine(BlockState state, CallbackInfoReturnable cir) { + if (holdingObsidianPickaxe() && state.isOf(Blocks.OBSIDIAN)) { + cir.setReturnValue(true); + } + } + +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinSettingsManager.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinSettingsManager.java new file mode 100644 index 0000000..df66639 --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinSettingsManager.java @@ -0,0 +1,18 @@ +package com.github.zly2006.carpetslsaddition.mixin; + +import carpet.api.settings.SettingsManager; +import com.github.zly2006.carpetslsaddition.SettingsManagerAccessor; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.nio.file.Path; + +@Mixin(value = SettingsManager.class, remap = false) +public abstract class MixinSettingsManager implements SettingsManagerAccessor { + @Shadow protected abstract void loadConfigurationFromConf(); + + @Override + public void loadSettings() { + this.loadConfigurationFromConf(); + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 335610b..1f333d5 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -24,7 +24,7 @@ ], "depends": { - "fabricloader": ">=0.14.9", + "fabricloader": ">=0.13", "fabric-api": "*", "minecraft": "~1.19", "java": ">=17", diff --git a/src/main/resources/slsaddition.mixins.json b/src/main/resources/slsaddition.mixins.json index 262bc1d..f11db13 100644 --- a/src/main/resources/slsaddition.mixins.json +++ b/src/main/resources/slsaddition.mixins.json @@ -6,9 +6,13 @@ "mixins": [ "AccessorPlayerAbilities", "MixinAbstractSignBlock", + "MixinBlock", "MixinFallingBlockEntity", + "MixinItem", "MixinItemEntity", + "MixinPlayerEntity", "MixinPlayerInventory", + "MixinSettingsManager", "MixinSpawnHelper", "MixinVillagerEntity" ],