Skip to content

B站视频资源

视频: https://www.bilibili.com/video/BV1zADtYGEuQ/
MC 百科: https://www.mcmod.cn/class/16961.html

视频中使用的枪包是由 Rhodes_koei 创作的 机动军械师

TypeScript 参考类型可以在 types 中找到.

如果你遇到了问题

你可以在上面的视频底下留言, 或加入我的 QQ 群 324617456 交流.

视频中使用到的代码

注意

下面提供的代码是模组版本 1.3.0 之前写的。
因为 TaCZ 有过一次大更新,所以不保证代码依旧可用。

左键攻击右键检视武器,启用原版交互

点我查看代码
javascript
// client_scripts/melee.js

const $HitResult$Type = Java.tryLoadClass("net.minecraft.world.phys.HitResult$Type");
const $IWrenchable = Java.tryLoadClass("com.simibubi.create.content.equipment.wrench.IWrenchable");

const MeleeWeapons = ["create_armorer:special_melee_wrench", "create_armorer:special_melee_atomic"];

// 被视为扳手的枪械
const Wrenchs = ["create_armorer:special_melee_wrench"];

// 是否播放交互动画
const PlayInteractAnimation = true;

// https://github.com/Creators-of-Create/Create/blob/d48a504486311f3175f4ebef3b0649140e728fbb/src/generated/resources/data/create/tags/blocks/wrench_pickup.json
const WrenchPickup = [
  "create:andesite_bars",
  "create:brass_bars",
  "create:copper_bars",
  "create:industrial_iron_block",
  "minecraft:redstone_wire",
  "minecraft:redstone_torch",
  "minecraft:repeater",
  "minecraft:lever",
  "minecraft:comparator",
  "minecraft:observer",
  "minecraft:redstone_wall_torch",
  "minecraft:piston",
  "minecraft:sticky_piston",
  "minecraft:tripwire",
  "minecraft:tripwire_hook",
  "minecraft:daylight_detector",
  "minecraft:target",
  "minecraft:hopper",
  "#minecraft:buttons",
  "#minecraft:pressure_plates",
  "#minecraft:rails",
];

TaCZClientEvents.gunIndexLoad((event) => {
  if (MeleeWeapons.includes(event.getGunId().toString())) {
    // 为近战武器添加原版交互设置
    event.setVanillaInteract(true);
  }
});

TaCZClientEvents.playerAim((event) => {
  const gunId = event.getGunId().toString();
  if (MeleeWeapons.includes(gunId)) {
    // 只处理开始瞄准的事件
    if (!event.isAim()) return;

    // 如果是原版交互并且可以交互, 播放交互动画并取消瞄准
    if (event.isVanillaInteract() && event.canInteractEntity()) {
      if (PlayInteractAnimation) {
        TaCZJSUtils.SoundPlayManager.stopPlayGunSound();
        event.runMaimAnimation(
          "melee_bayonet_1",
          TaCZJSUtils.AnimationPlayType.PLAY_ONCE_STOP,
          0.2
        );
      }
      return event.cancelAim();
    }

    const blockHitResult = event.getBlockHitResult();
    if (
      Wrenchs.includes(gunId) &&
      blockHitResult !== null &&
      blockHitResult.getType() === $HitResult$Type.BLOCK
    ) {
      const state = event.getLevel().getBlockState(blockHitResult.getBlockPos());
      const block = state.getBlock();

      // 如果是可旋转方块或者可拾取的方块, 播放交互动画并取消瞄准
      if (
        block instanceof $IWrenchable ||
        WrenchPickup.includes(state.getBlock().getIdLocation().toString())
      ) {
        if (PlayInteractAnimation) {
          TaCZJSUtils.SoundPlayManager.stopPlayGunSound();
          event.runMaimAnimation(
            "melee_bayonet_1",
            TaCZJSUtils.AnimationPlayType.PLAY_ONCE_STOP,
            0.2
          );
        }
        return event.cancelAim();
      }
    }

    event.cancelAim();
    const gunIndex = event.getGunIndex();
    const am = gunIndex.getAnimationStateMachine();
    if (am === null) return;
    if (am.isPlayingRunIntroOrLoop()) {
      // 如果正在跑步, 播放 run_start 动画
      event.runMovementAnimation("run_start", TaCZJSUtils.AnimationPlayType.PLAY_ONCE_HOLD, 0.2);
    } else if (am.isPlayingIdleAnimation() || am.isPlayingWalkAnimation()) {
      // 如果正在站立或者走路, 播放武器检视动画
      TaCZJSUtils.SoundPlayManager.stopPlayGunSound();
      TaCZJSUtils.SoundPlayManager.playInspectSound(event.getPlayer(), gunIndex, false);
      am.onGunInspect();
    }
  }
});

TaCZClientEvents.playerShoot((event) => {
  if (MeleeWeapons.includes(event.getGunId().toString())) {
    // 停止播放音效
    TaCZJSUtils.SoundPlayManager.stopPlayGunSound();
    // 如果近战武器进行射击, 取消射击并执行近战
    event.cancelShoot();
    event.getGunOperator().melee();
  }
});

机动军械师 的扳手拥有机械动力的扳手的功能

点我查看代码
javascript
// server_scripts/wrench.js

const $Random = Java.tryLoadClass("java.util.Random");
const RANDOM = new $Random();
const $HitResult$Type = Java.tryLoadClass("net.minecraft.world.phys.HitResult$Type");
const $BlockHitResult = Java.tryLoadClass("net.minecraft.world.phys.BlockHitResult");
const $UseOnContext = Java.tryLoadClass("net.minecraft.world.item.context.UseOnContext");
const $AllSoundEvents = Java.tryLoadClass("com.simibubi.create.AllSoundEvents");
const $InteractionHand = Java.tryLoadClass("net.minecraft.world.InteractionHand");
const $IWrenchable = Java.tryLoadClass("com.simibubi.create.content.equipment.wrench.IWrenchable");
const $Block = Java.tryLoadClass("net.minecraft.world.level.block.Block");
const $ItemStack = Java.tryLoadClass("net.minecraft.world.item.ItemStack");

// https://github.com/Creators-of-Create/Create/blob/d48a504486311f3175f4ebef3b0649140e728fbb/src/generated/resources/data/create/tags/blocks/wrench_pickup.json
const WrenchPickup = [
  "create:andesite_bars",
  "create:brass_bars",
  "create:copper_bars",
  "create:industrial_iron_block",
  "minecraft:redstone_wire",
  "minecraft:redstone_torch",
  "minecraft:repeater",
  "minecraft:lever",
  "minecraft:comparator",
  "minecraft:observer",
  "minecraft:redstone_wall_torch",
  "minecraft:piston",
  "minecraft:sticky_piston",
  "minecraft:tripwire",
  "minecraft:tripwire_hook",
  "minecraft:daylight_detector",
  "minecraft:target",
  "minecraft:hopper",
  "#minecraft:buttons",
  "#minecraft:pressure_plates",
  "#minecraft:rails",
];

const Wrenchs = ["create_armorer:special_melee_wrench"];

ItemEvents.firstRightClicked((event) => {
  const item = event.getItem();
  if (item.equals(Item.of("minecraft:air"))) return;

  const target = event.getTarget();
  if (
    (target !== null && target.type.toString() !== $HitResult$Type.BLOCK.toString()) ||
    !(
      item.getId().toString() === "tacz:modern_kinetic_gun" &&
      Wrenchs.includes(item.getNbt().getString("GunId"))
    )
  ) {
    return;
  }

  const state = target.block.getBlockState();
  const block = state.getBlock();
  const world = event.getLevel();
  const player = event.getPlayer();
  const blockHitResult = new $BlockHitResult(
    target.hit,
    target.facing,
    target.block.getPos(),
    false
  );
  const context = new $UseOnContext(
    world,
    player,
    $InteractionHand.MAIN_HAND,
    item,
    blockHitResult
  );

  if (block instanceof $IWrenchable) {
    const actor = block;
    player.isShiftKeyDown()
      ? actor.onSneakWrenched(state, context)
      : actor.onWrenched(state, context);
  } else {
    player.isShiftKeyDown() &&
      WrenchPickup.includes(state.getBlock().getIdLocation().toString()) &&
      onItemUseOnOther(player, world, target, item);
  }
});

function onItemUseOnOther(player, world, target, item) {
  const state = target.block.getBlockState();
  const pos = target.block.getPos();
  if (player !== null && !player.isCreative()) {
    $Block
      .getDrops(state, world, pos, world.getBlockEntity(pos), player, item)
      .forEach((itemStack) => {
        player.getInventory().placeItemBackInInventory(itemStack);
      });
  }
  state.spawnAfterBreak(world, pos, $ItemStack.EMPTY, true);
  world.destroyBlock(pos, false);
  $AllSoundEvents.WRENCH_REMOVE.playOnServer(world, pos, 1.0, RANDOM.nextFloat() * 0.5 + 0.5);
}

赞助 ❤️

喜欢 TaCZ JS 吗?你可以在 爱发电 对我进行赞助,助力模组持续更新!

金主爸爸

Released under the CC BY-NC-SA 4.0.