Compare commits
No commits in common. "bfc37b3b6178db3faef532d438b79c2266c36d39" and "c381874b8701a44a4797d4acadd1148d3c1133fa" have entirely different histories.
bfc37b3b61
...
c381874b87
@ -669,7 +669,7 @@ Also add information on how to contact you by electronic and paper mail.
|
|||||||
If the program does terminal interaction, make it output a short
|
If the program does terminal interaction, make it output a short
|
||||||
notice like this when it starts in an interactive mode:
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
AutoCrossbow Copyright (C) 2025 BRanulf
|
{project} Copyright (C) {year} {fullname}
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
This is free software, and you are welcome to redistribute it
|
This is free software, and you are welcome to redistribute it
|
||||||
under certain conditions; type `show c' for details.
|
under certain conditions; type `show c' for details.
|
||||||
|
@ -6,7 +6,7 @@ minecraft_version=1.21.4
|
|||||||
yarn_mappings=1.21.4+build.8
|
yarn_mappings=1.21.4+build.8
|
||||||
loader_version=0.16.10
|
loader_version=0.16.10
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=1.14.514.006
|
mod_version=1.14.514.004
|
||||||
maven_group=com.example
|
maven_group=com.example
|
||||||
archives_base_name=autocrossbow
|
archives_base_name=autocrossbow
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https://mirrors.aliyun.com/macports/distfiles/gradle/gradle-8.14.3-bin.zip
|
distributionUrl=https://mirrors.aliyun.com/macports/distfiles/gradle/gradle-8.14.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
@ -1,103 +1,46 @@
|
|||||||
package com.example.autocrossbow;
|
package com.example.autocrossbow;
|
||||||
|
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
|
|
||||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
|
|
||||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.option.KeyBinding;
|
import net.minecraft.client.option.KeyBinding;
|
||||||
import net.minecraft.client.util.InputUtil;
|
import net.minecraft.client.util.InputUtil;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
|
||||||
import net.minecraft.item.CrossbowItem;
|
import net.minecraft.item.CrossbowItem;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket;
|
|
||||||
import net.minecraft.screen.slot.SlotActionType;
|
|
||||||
import net.minecraft.text.ClickEvent;
|
|
||||||
import net.minecraft.text.MutableText;
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import com.mojang.brigadier.arguments.BoolArgumentType;
|
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
|
||||||
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
public class AutoCrossbowMod implements ClientModInitializer {
|
public class AutoCrossbowMod implements ClientModInitializer {
|
||||||
|
|
||||||
|
|
||||||
private static boolean enabled = false;
|
private static boolean enabled = false;
|
||||||
private static AutoCrossbowMode currentMode = AutoCrossbowMode.NORMAL;
|
private static KeyBinding toggleKeyBinding;
|
||||||
|
private static boolean wasUsing = false;
|
||||||
|
|
||||||
private static KeyBinding toggleModKeyBinding;
|
|
||||||
private static KeyBinding toggleModeKeyBinding;
|
|
||||||
|
|
||||||
|
|
||||||
private static boolean isRightClickPressed = false;
|
|
||||||
private static boolean wasRightClickPressed = false;
|
|
||||||
|
|
||||||
private static int chargeProgress = 0;
|
private static int chargeProgress = 0;
|
||||||
|
|
||||||
private static long lastActionTime = 0;
|
|
||||||
private static final long ACTION_COOLDOWN_MS = 50;
|
|
||||||
|
|
||||||
public enum AutoCrossbowMode {
|
|
||||||
NORMAL("normal"), // 普通自动
|
|
||||||
RAPID_FIRE_SHOOT("rapid_shoot"), // 连发发射
|
|
||||||
RAPID_FIRE_LOAD("rapid_load"); // 连发装填
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
AutoCrossbowMode(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AutoCrossbowMode fromString(String text) {
|
|
||||||
for (AutoCrossbowMode mode : AutoCrossbowMode.values()) {
|
|
||||||
if (mode.name.equalsIgnoreCase(text)) {
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AutoCrossbowMode next() {
|
|
||||||
return values()[(this.ordinal() + 1) % values().length];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeClient() {
|
public void onInitializeClient() {
|
||||||
|
toggleKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding(
|
||||||
toggleModKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding(
|
"key.autocrossbow.toggle",
|
||||||
"key.autocrossbow.toggle_mod",
|
|
||||||
InputUtil.Type.KEYSYM,
|
InputUtil.Type.KEYSYM,
|
||||||
GLFW.GLFW_KEY_UNKNOWN,
|
GLFW.GLFW_KEY_UNKNOWN, // 默认UNKNOW,自己去设置
|
||||||
"category.autocrossbow"
|
"category.autocrossbow"
|
||||||
));
|
));
|
||||||
|
|
||||||
toggleModeKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding(
|
|
||||||
"key.autocrossbow.toggle_mode",
|
|
||||||
InputUtil.Type.KEYSYM,
|
|
||||||
GLFW.GLFW_KEY_UNKNOWN,
|
|
||||||
"category.autocrossbow"
|
|
||||||
));
|
|
||||||
|
|
||||||
|
|
||||||
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
||||||
handleKeybinds(client);
|
while (toggleKeyBinding.wasPressed()) {
|
||||||
|
enabled = !enabled;
|
||||||
|
if (client.player != null) {
|
||||||
|
client.player.sendMessage(
|
||||||
|
Text.translatable("message.autocrossbow.status",
|
||||||
|
Text.translatable(enabled ? "message.autocrossbow.enabled" : "message.autocrossbow.disabled")),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!enabled || client.player == null || client.interactionManager == null) {
|
if (!enabled || client.player == null || client.interactionManager == null) {
|
||||||
return;
|
return;
|
||||||
@ -107,290 +50,38 @@ public class AutoCrossbowMod implements ClientModInitializer {
|
|||||||
Hand hand = Hand.MAIN_HAND;
|
Hand hand = Hand.MAIN_HAND;
|
||||||
ItemStack stack = player.getStackInHand(hand);
|
ItemStack stack = player.getStackInHand(hand);
|
||||||
|
|
||||||
isRightClickPressed = client.options.useKey.isPressed();
|
|
||||||
|
|
||||||
if (!(stack.getItem() instanceof CrossbowItem)) {
|
if (!(stack.getItem() instanceof CrossbowItem)) {
|
||||||
|
|
||||||
resetActionStates();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isUsing = client.options.useKey.isPressed();
|
||||||
|
|
||||||
switch (currentMode) {
|
if (CrossbowItem.isCharged(stack) && isUsing) {
|
||||||
case NORMAL:
|
|
||||||
handleNormalMode(client, player, hand, stack);
|
|
||||||
break;
|
|
||||||
case RAPID_FIRE_SHOOT:
|
|
||||||
handleRapidFireShootMode(client, player, hand, stack);
|
|
||||||
break;
|
|
||||||
case RAPID_FIRE_LOAD:
|
|
||||||
handleRapidFireLoadMode(client, player, hand, stack);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
wasRightClickPressed = isRightClickPressed;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
|
|
||||||
dispatcher.register(ClientCommandManager.literal("autocrossbow")
|
|
||||||
.executes(context -> {
|
|
||||||
|
|
||||||
PlayerEntity player = MinecraftClient.getInstance().player;
|
|
||||||
if (player != null) {
|
|
||||||
player.sendMessage(Text.translatable("command.autocrossbow.status",
|
|
||||||
Text.translatable(enabled ? "message.autocrossbow.enabled" : "message.autocrossbow.disabled"),
|
|
||||||
Text.translatable("message.autocrossbow.mode." + currentMode.getName())), false);
|
|
||||||
|
|
||||||
|
|
||||||
MutableText toggleEnabledText = Text.translatable("command.autocrossbow.toggle_enabled")
|
|
||||||
.styled(s -> s.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/autocrossbow enabled " + !enabled)));
|
|
||||||
player.sendMessage(toggleEnabledText, false);
|
|
||||||
|
|
||||||
|
|
||||||
MutableText toggleModeText = Text.translatable("command.autocrossbow.toggle_mode")
|
|
||||||
.styled(s -> s.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/autocrossbow mode " + currentMode.next().getName())));
|
|
||||||
player.sendMessage(toggleModeText, false);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
})
|
|
||||||
.then(ClientCommandManager.literal("enabled")
|
|
||||||
.then(ClientCommandManager.argument("value", BoolArgumentType.bool())
|
|
||||||
.executes(context -> {
|
|
||||||
enabled = BoolArgumentType.getBool(context, "value");
|
|
||||||
PlayerEntity player = MinecraftClient.getInstance().player;
|
|
||||||
if (player != null) {
|
|
||||||
player.sendMessage(Text.translatable("message.autocrossbow.status",
|
|
||||||
Text.translatable(enabled ? "message.autocrossbow.enabled" : "message.autocrossbow.disabled"),
|
|
||||||
Text.translatable("message.autocrossbow.mode." + currentMode.getName())), false);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.then(ClientCommandManager.literal("mode")
|
|
||||||
.then(ClientCommandManager.argument("modeName", StringArgumentType.word())
|
|
||||||
.suggests(MODE_SUGGESTION_PROVIDER)
|
|
||||||
.executes(context -> {
|
|
||||||
String modeName = StringArgumentType.getString(context, "modeName");
|
|
||||||
AutoCrossbowMode newMode = AutoCrossbowMode.fromString(modeName);
|
|
||||||
PlayerEntity player = MinecraftClient.getInstance().player;
|
|
||||||
if (newMode != null) {
|
|
||||||
currentMode = newMode;
|
|
||||||
if (player != null) {
|
|
||||||
player.sendMessage(Text.translatable("message.autocrossbow.mode_changed",
|
|
||||||
Text.translatable("message.autocrossbow.mode." + currentMode.getName())), false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (player != null) {
|
|
||||||
player.sendMessage(Text.translatable("command.autocrossbow.invalid_mode", modeName), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void handleKeybinds(MinecraftClient client) {
|
|
||||||
while (toggleModKeyBinding.wasPressed()) {
|
|
||||||
enabled = !enabled;
|
|
||||||
if (client.player != null) {
|
|
||||||
client.player.sendMessage(
|
|
||||||
Text.translatable("message.autocrossbow.status",
|
|
||||||
Text.translatable(enabled ? "message.autocrossbow.enabled" : "message.autocrossbow.disabled"),
|
|
||||||
Text.translatable("message.autocrossbow.mode." + currentMode.getName())),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (toggleModeKeyBinding.wasPressed()) {
|
|
||||||
currentMode = currentMode.next();
|
|
||||||
if (client.player != null) {
|
|
||||||
client.player.sendMessage(
|
|
||||||
Text.translatable("message.autocrossbow.mode_changed",
|
|
||||||
Text.translatable("message.autocrossbow.mode." + currentMode.getName())),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void resetActionStates() {
|
|
||||||
isRightClickPressed = false;
|
|
||||||
wasRightClickPressed = false;
|
|
||||||
chargeProgress = 0;
|
|
||||||
lastActionTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void handleNormalMode(MinecraftClient client, PlayerEntity player, Hand hand, ItemStack stack) {
|
|
||||||
if (CrossbowItem.isCharged(stack) && isRightClickPressed) {
|
|
||||||
|
|
||||||
client.interactionManager.interactItem(player, hand);
|
client.interactionManager.interactItem(player, hand);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRightClickPressed) {
|
if (isUsing) {
|
||||||
|
|
||||||
if (!player.isUsingItem()) {
|
if (!player.isUsingItem()) {
|
||||||
client.interactionManager.interactItem(player, hand);
|
client.interactionManager.interactItem(player, hand);
|
||||||
chargeProgress = 0;
|
chargeProgress = 0;
|
||||||
} else if (player.getActiveHand() == hand) {
|
}
|
||||||
|
else if (player.getActiveHand() == hand) {
|
||||||
chargeProgress++;
|
chargeProgress++;
|
||||||
|
|
||||||
int pullTime = CrossbowItem.getPullTime(stack, player);
|
int pullTime = CrossbowItem.getPullTime(stack, player);
|
||||||
|
|
||||||
|
// TODO 目前测试稳定的只有快速装填3,其他有待优化
|
||||||
if (chargeProgress >= pullTime * 1.1f) {
|
if (chargeProgress >= pullTime * 1.1f) {
|
||||||
client.interactionManager.stopUsingItem(player);
|
client.interactionManager.stopUsingItem(player);
|
||||||
|
wasUsing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (wasRightClickPressed) {
|
}
|
||||||
|
else if (wasUsing) {
|
||||||
|
wasUsing = false;
|
||||||
chargeProgress = 0;
|
chargeProgress = 0;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void handleRapidFireShootMode(MinecraftClient client, PlayerEntity player, Hand hand, ItemStack stack) {
|
|
||||||
if (!isRightClickPressed) {
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (System.currentTimeMillis() - lastActionTime < ACTION_COOLDOWN_MS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CrossbowItem.isCharged(stack)) {
|
|
||||||
|
|
||||||
client.interactionManager.interactItem(player, hand);
|
|
||||||
player.swingHand(hand);
|
|
||||||
lastActionTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int nextSlot = findNextCrossbow(player.getInventory(), true, player.getInventory().selectedSlot);
|
|
||||||
if (nextSlot != -1) {
|
|
||||||
swapToSlot(client, player, nextSlot);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
player.sendMessage(Text.translatable("message.autocrossbow.no_more_charged"), true);
|
|
||||||
currentMode = AutoCrossbowMode.NORMAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void handleRapidFireLoadMode(MinecraftClient client, PlayerEntity player, Hand hand, ItemStack stack) {
|
|
||||||
if (!isRightClickPressed) {
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (player.isUsingItem() && player.getActiveHand() == hand) {
|
|
||||||
chargeProgress++;
|
|
||||||
int pullTime = CrossbowItem.getPullTime(stack, player);
|
|
||||||
|
|
||||||
if (chargeProgress >= pullTime * 1.1f) {
|
|
||||||
|
|
||||||
client.interactionManager.stopUsingItem(player);
|
|
||||||
chargeProgress = 0;
|
|
||||||
lastActionTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
|
|
||||||
int nextSlot = findNextCrossbow(player.getInventory(), false, player.getInventory().selectedSlot);
|
|
||||||
if (nextSlot != -1) {
|
|
||||||
swapToSlot(client, player, nextSlot);
|
|
||||||
} else {
|
|
||||||
player.sendMessage(Text.translatable("message.autocrossbow.no_more_uncharged"), true);
|
|
||||||
currentMode = AutoCrossbowMode.NORMAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!CrossbowItem.isCharged(stack)) {
|
|
||||||
|
|
||||||
|
|
||||||
if (System.currentTimeMillis() - lastActionTime < ACTION_COOLDOWN_MS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
client.interactionManager.interactItem(player, hand);
|
|
||||||
chargeProgress = 0;
|
|
||||||
lastActionTime = System.currentTimeMillis();
|
|
||||||
} else {
|
|
||||||
|
|
||||||
|
|
||||||
if (System.currentTimeMillis() - lastActionTime < ACTION_COOLDOWN_MS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int nextSlot = findNextCrossbow(player.getInventory(), false, player.getInventory().selectedSlot);
|
|
||||||
if (nextSlot != -1) {
|
|
||||||
swapToSlot(client, player, nextSlot);
|
|
||||||
lastActionTime = System.currentTimeMillis();
|
|
||||||
} else {
|
|
||||||
player.sendMessage(Text.translatable("message.autocrossbow.no_more_uncharged"), true);
|
|
||||||
currentMode = AutoCrossbowMode.NORMAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int findNextCrossbow(PlayerInventory inventory, boolean chargedRequired, int currentSelectedSlot) {
|
|
||||||
|
|
||||||
for (int i = 0; i < PlayerInventory.HOTBAR_SIZE; i++) {
|
|
||||||
if (i == currentSelectedSlot) continue;
|
|
||||||
|
|
||||||
ItemStack stack = inventory.getStack(i);
|
|
||||||
if (stack.getItem() instanceof CrossbowItem) {
|
|
||||||
boolean isCharged = CrossbowItem.isCharged(stack);
|
|
||||||
if (chargedRequired == isCharged) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = PlayerInventory.HOTBAR_SIZE; i < inventory.main.size(); i++) {
|
|
||||||
ItemStack stack = inventory.getStack(i);
|
|
||||||
if (stack.getItem() instanceof CrossbowItem) {
|
|
||||||
boolean isCharged = CrossbowItem.isCharged(stack);
|
|
||||||
if (chargedRequired == isCharged) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void swapToSlot(MinecraftClient client, PlayerEntity player, int targetSlot) {
|
|
||||||
if (client.interactionManager == null || player.playerScreenHandler == null) return;
|
|
||||||
|
|
||||||
if (targetSlot >= 0 && targetSlot < PlayerInventory.HOTBAR_SIZE) {
|
|
||||||
player.getInventory().selectedSlot = targetSlot;
|
|
||||||
|
|
||||||
client.getNetworkHandler().sendPacket(new UpdateSelectedSlotC2SPacket(targetSlot));
|
|
||||||
} else {
|
|
||||||
|
|
||||||
client.interactionManager.clickSlot(
|
|
||||||
player.playerScreenHandler.syncId,
|
|
||||||
targetSlot,
|
|
||||||
player.getInventory().selectedSlot,
|
|
||||||
SlotActionType.SWAP,
|
|
||||||
player
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final SuggestionProvider<FabricClientCommandSource> MODE_SUGGESTION_PROVIDER = (context, builder) -> {
|
|
||||||
Arrays.stream(AutoCrossbowMode.values())
|
|
||||||
.map(AutoCrossbowMode::getName)
|
|
||||||
.forEach(builder::suggest);
|
|
||||||
return builder.buildFuture();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.example.autocrossbow.client;
|
||||||
|
|
||||||
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
|
|
||||||
|
public class AutoCrossbowModClient implements ClientModInitializer {
|
||||||
|
|
||||||
|
// 额
|
||||||
|
@Override
|
||||||
|
public void onInitializeClient() {
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,7 @@
|
|||||||
{
|
{
|
||||||
"key.autocrossbow.toggle_mod": "Toggle Auto Crossbow Mod",
|
"key.autocrossbow.toggle": "Toggle Auto Crossbow",
|
||||||
"key.autocrossbow.toggle_mode": "Cycle Crossbow Mode",
|
|
||||||
"category.autocrossbow": "Auto Crossbow Mod",
|
"category.autocrossbow": "Auto Crossbow Mod",
|
||||||
"message.autocrossbow.status": "Auto Crossbow: %s, Mode: %s",
|
"message.autocrossbow.status": "Auto Crossbow: %s",
|
||||||
"message.autocrossbow.enabled": "Enabled",
|
"message.autocrossbow.enabled": "Enabled",
|
||||||
"message.autocrossbow.disabled": "Disabled",
|
"message.autocrossbow.disabled": "Disabled"
|
||||||
"message.autocrossbow.mode_changed": "Crossbow Mode: %s",
|
|
||||||
"message.autocrossbow.mode.normal": "Normal",
|
|
||||||
"message.autocrossbow.mode.rapid_shoot": "Rapid Fire (Shoot)",
|
|
||||||
"message.autocrossbow.mode.rapid_load": "Rapid Fire (Load)",
|
|
||||||
"message.autocrossbow.no_more_charged": "No more charged crossbows found!",
|
|
||||||
"message.autocrossbow.no_more_uncharged": "No more uncharged crossbows found!",
|
|
||||||
"command.autocrossbow.status": "§b[Auto Crossbow]§f Status: %s, Mode: %s",
|
|
||||||
"command.autocrossbow.toggle_enabled": "Click to toggle mod enabled/disabled",
|
|
||||||
"command.autocrossbow.toggle_mode": "Click to cycle mode",
|
|
||||||
"command.autocrossbow.invalid_mode": "Invalid mode: '%s'. Available modes: normal, rapid_shoot, rapid_load."
|
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,7 @@
|
|||||||
{
|
{
|
||||||
"key.autocrossbow.toggle_mod": "切换诸葛连弩开关",
|
"key.autocrossbow.toggle": "切换连弩模式",
|
||||||
"key.autocrossbow.toggle_mode": "切换连弩模式",
|
|
||||||
"category.autocrossbow": "诸葛连弩",
|
"category.autocrossbow": "诸葛连弩",
|
||||||
"message.autocrossbow.status": "§b[诸葛连弩]§f 状态:%s,模式:%s",
|
"message.autocrossbow.status": "§b[诸葛连弩]§f 状态: %s",
|
||||||
"message.autocrossbow.enabled": "§a已启用",
|
"message.autocrossbow.enabled": "§a已启用",
|
||||||
"message.autocrossbow.disabled": "§c已禁用",
|
"message.autocrossbow.disabled": "§c已禁用"
|
||||||
"message.autocrossbow.mode_changed": "连弩模式:%s",
|
|
||||||
"message.autocrossbow.mode.normal": "正常模式",
|
|
||||||
"message.autocrossbow.mode.rapid_shoot": "连发 - 发射模式",
|
|
||||||
"message.autocrossbow.mode.rapid_load": "连发 - 装填模式",
|
|
||||||
"message.autocrossbow.no_more_charged": "背包中没有更多已上膛的弩了!",
|
|
||||||
"message.autocrossbow.no_more_uncharged": "背包中没有更多未上膛的弩了!",
|
|
||||||
"command.autocrossbow.status": "§b[诸葛连弩]§f 状态:%s,模式:%s",
|
|
||||||
"command.autocrossbow.toggle_enabled": "点击切换模组启用/禁用",
|
|
||||||
"command.autocrossbow.toggle_mode": "点击切换模式",
|
|
||||||
"command.autocrossbow.invalid_mode": "无效模式:“%s”。可用模式:normal, rapid_shoot, rapid_load。"
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user