Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,12 @@ dependencies {
jarJar.ranged(it, "[0.3.6,)")
}
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
implementation 'it.unimi.dsi:fastutil:8.5.18'
/*
implementation(jarJar('it.unimi.dsi:fastutil:8.5.18')) {
jarJar.ranged(it, '[8.5,9.0)')
}*/
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
}

jar {
Expand All @@ -262,4 +268,4 @@ java {

tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/tacz/guns/GunMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.tacz.guns.init.*;
import com.tacz.guns.resource.GunPackLoader;
import com.tacz.guns.resource.modifier.AttachmentPropertyManager;
import com.tacz.guns.util.ShootBus;
import net.minecraft.server.packs.PackType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.IEventBus;
Expand All @@ -28,7 +29,6 @@ public class GunMod {
* 默认模型包文件夹
*/
public static final String DEFAULT_GUN_PACK_NAME = "tacz_default_gun";

public GunMod() {
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, CommonConfig.init());
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ServerConfig.init());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ static IClientPlayerGunOperator fromLocalPlayer(LocalPlayer player) {
*/
ShootResult shoot();

/**
* 停止全自动射击
*/
void stopFullAuto();

/**
* 执行客户端切枪逻辑。
*/
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/com/tacz/guns/api/entity/IGunOperator.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,29 @@ static IGunOperator fromLivingEntity(LivingEntity entity) {
*/
ShootResult shoot(Supplier<Float> pitch, Supplier<Float> yaw, long timestamp);

/**
* 从实体的位置,向指定的方向开枪。计算冷却的时候使用指定的 timestamp。指定包含的弹药数和射击发起的来源
*
* @param pitch 开火方向的俯仰角(即 xRot )
* @param yaw 开火方向的偏航角(即 yRot )
* @param timestamp 指定的时间戳,为偏移时间戳(相对于 base timestamp 的时间戳)
* @param count 包含的弹药数
* @param fromServer true为来自服务器,false为来自客户端
* @return 本次射击的结果
*/
ShootResult shoot(Supplier<Float> pitch, Supplier<Float> yaw, long timestamp, int count, boolean fromServer);

/**
* 开始全自动射击
* @param timestamp 开始的时间戳
*/
void startFullAuto(long timestamp);

/**
* 停止全自动射击
*/
void stopFullAuto();

/**
* 服务端,该操作者是否受弹药数影响
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private static Comparator<Map.Entry<ResourceLocation, CommonGunIndex>> idNameSor
/**
* 射击时触发
*/
public abstract void shoot(ShooterDataHolder dataHolder, ItemStack gunItem, Supplier<Float> pitch, Supplier<Float> yaw, LivingEntity shooter);
public abstract void shoot(ShooterDataHolder dataHolder, ItemStack gunItem, Supplier<Float> pitch, Supplier<Float> yaw, LivingEntity shooter, int count);

/**
* 开始换弹时调用
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tacz.guns.client.gameplay;

import com.tacz.guns.GunMod;
import com.tacz.guns.api.TimelessAPI;
import com.tacz.guns.api.client.animation.statemachine.AnimationStateMachine;
import com.tacz.guns.api.client.gameplay.IClientPlayerGunOperator;
Expand All @@ -15,12 +16,15 @@
import com.tacz.guns.client.sound.SoundPlayManager;
import com.tacz.guns.network.NetworkHandler;
import com.tacz.guns.network.message.ClientMessagePlayerShoot;
import com.tacz.guns.network.message.ClientMessagePlayerShootBegin;
import com.tacz.guns.network.message.ClientMessagePlayerShootEnd;
import com.tacz.guns.resource.index.CommonGunIndex;
import com.tacz.guns.resource.modifier.AttachmentCacheProperty;
import com.tacz.guns.resource.modifier.custom.SilenceModifier;
import com.tacz.guns.resource.pojo.data.gun.Bolt;
import com.tacz.guns.resource.pojo.data.gun.GunData;
import com.tacz.guns.sound.SoundManager;
import com.tacz.guns.util.ShootBus;
import it.unimi.dsi.fastutil.Pair;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
Expand All @@ -30,6 +34,8 @@
import net.minecraftforge.fml.LogicalSide;

import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
Expand All @@ -39,6 +45,13 @@ public class LocalPlayerShoot {
private static final Predicate<IGunOperator> SHOOT_LOCKED_CONDITION = operator -> operator.getSynShootCoolDown() > 0;
private final LocalPlayerDataHolder data;
private final LocalPlayer player;
private static final ScheduledExecutorService SHOOT_SCHEDULER =
Executors.newSingleThreadScheduledExecutor(r -> {
Thread t = new Thread(r, "Gun-AutoShoot-Scheduler");
t.setDaemon(true);
return t;
});
private ScheduledFuture<?> shootTask;

public LocalPlayerShoot(LocalPlayerDataHolder data, LocalPlayer player) {
this.data = data;
Expand Down Expand Up @@ -144,6 +157,41 @@ public ShootResult shoot() {

private void doShoot(GunDisplayInstance display, IGun iGun, ItemStack mainHandItem, GunData gunData, long delay) {
FireMode fireMode = iGun.getFireMode(mainHandItem);
//如果是全自动则按照射速应用后坐力,直到松开射击键或弹药耗尽由服务器调用stopFullAuto()
if(fireMode == FireMode.AUTO) {
data.isShootRecorded = true;
NetworkHandler.CHANNEL.sendToServer(new ClientMessagePlayerShootBegin(data.clientShootTimestamp - data.clientBaseTimestamp));
int rpm = iGun.getRPM(this.player.getMainHandItem());
double roundsPerSecond = rpm / 60.0;
long intervalNanos = (long) (1_000_000_000.0 / roundsPerSecond);
ScheduledFuture<?> task = SHOOT_SCHEDULER.scheduleAtFixedRate(
() -> {
Minecraft.getInstance().submitAsync(() -> {
// 触发击发事件
boolean fire = !MinecraftForge.EVENT_BUS.post(new GunFireEvent(player, mainHandItem, LogicalSide.CLIENT));
if (fire) {
// 动画和声音循环播放
AnimationStateMachine<?> animationStateMachine = display.getAnimationStateMachine();
if (animationStateMachine != null) {
animationStateMachine.trigger(GunAnimationConstant.INPUT_SHOOT);
}
// 获取消音
final boolean useSilenceSound = this.useSilenceSound();
// 开火需要打断检视
SoundPlayManager.stopPlayGunSound(display, SoundManager.INSPECT_SOUND);
if (useSilenceSound) {
SoundPlayManager.playSilenceSound(player, display, gunData);
} else {
SoundPlayManager.playShootSound(player, display, gunData);
}
}
});
},
0, intervalNanos, TimeUnit.NANOSECONDS
);
shootTask = task;
return;
}
Bolt boltType = gunData.getBolt();
// 获取余弹数
boolean consumeAmmo = IGunOperator.fromLivingEntity(player).consumesAmmoOrNot();
Expand Down Expand Up @@ -216,7 +264,14 @@ private void doShoot(GunDisplayInstance display, IGun iGun, ItemStack mainHandIt
count.getAndIncrement();
}, delay, period, TimeUnit.MILLISECONDS);
}

public boolean stopFullAuto() {
data.isShootRecorded = true;
if(shootTask != null) {
shootTask.cancel(true);
}
NetworkHandler.CHANNEL.sendToServer(new ClientMessagePlayerShootEnd(data.clientShootTimestamp - data.clientBaseTimestamp));
return true;
}
private boolean useSilenceSound() {
AttachmentCacheProperty cacheProperty = IGunOperator.fromLivingEntity(player).getCacheProperty();
if (cacheProperty != null) {
Expand Down
13 changes: 10 additions & 3 deletions src/main/java/com/tacz/guns/client/input/ShootKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
@OnlyIn(Dist.CLIENT)
@Mod.EventBusSubscriber(value = Dist.CLIENT)
public class ShootKey {
public static boolean pushDown = false;
public static final KeyMapping SHOOT_KEY = new KeyMapping("key.tacz.shoot.desc",
KeyConflictContext.IN_GAME,
KeyModifier.NONE,
Expand Down Expand Up @@ -63,10 +64,16 @@ public static void autoShoot(TickEvent.ClientTickEvent event) {
// 非全自动情况,禁止连续开火
return;
}
if (operator.shoot() == ShootResult.SUCCESS) {
lastTimeShootSuccess = true;
//开始全自动射击
if(fireMode == FireMode.AUTO && !pushDown) {
if (operator.shoot() == ShootResult.SUCCESS) {
lastTimeShootSuccess = true;
}
pushDown = true;
}
} else {
operator.stopFullAuto();
pushDown = false;
lastTimeShootSuccess = false;
}
}
Expand Down Expand Up @@ -154,4 +161,4 @@ public static boolean semiShootController(boolean isPress) {
}
return false;
}
}
}
Loading