尝试合并武器切换相关处理

This commit is contained in:
Light_Quanta 2025-03-10 00:06:33 +08:00
parent 45e99ab220
commit e13ddc7f5d
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
4 changed files with 151 additions and 42 deletions

View file

@ -9,6 +9,7 @@ import com.atsuishio.superbwarfare.entity.vehicle.base.ContainerMobileVehicleEnt
import com.atsuishio.superbwarfare.entity.vehicle.base.LandArmorEntity;
import com.atsuishio.superbwarfare.entity.vehicle.base.WeaponVehicleEntity;
import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModifier;
import com.atsuishio.superbwarfare.entity.vehicle.weapon.VehicleWeapon;
import com.atsuishio.superbwarfare.init.*;
import com.atsuishio.superbwarfare.network.message.ShakeClientMessage;
import com.atsuishio.superbwarfare.tools.AmmoType;
@ -72,8 +73,6 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
public static final EntityDataAccessor<Integer> AMMO = SynchedEntityData.defineId(Yx100Entity.class, EntityDataSerializers.INT);
public static final EntityDataAccessor<Integer> MG_AMMO = SynchedEntityData.defineId(Yx100Entity.class, EntityDataSerializers.INT);
public static final EntityDataAccessor<Integer> LOADED_AMMO = SynchedEntityData.defineId(Yx100Entity.class, EntityDataSerializers.INT);
public static final EntityDataAccessor<Integer> WEAPON_TYPE = SynchedEntityData.defineId(Yx100Entity.class, EntityDataSerializers.INT);
public static final EntityDataAccessor<Integer> PASSENGER_WEAPON_TYPE = SynchedEntityData.defineId(Yx100Entity.class, EntityDataSerializers.INT);
public static final EntityDataAccessor<Float> TRACK_L = SynchedEntityData.defineId(Yx100Entity.class, EntityDataSerializers.FLOAT);
public static final EntityDataAccessor<Float> TRACK_R = SynchedEntityData.defineId(Yx100Entity.class, EntityDataSerializers.FLOAT);
public static final EntityDataAccessor<Float> YAW = SynchedEntityData.defineId(Yx100Entity.class, EntityDataSerializers.FLOAT);
@ -113,6 +112,20 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
this.setMaxUpStep(1.5f);
}
@Override
public VehicleWeapon[][] getAllWeapons() {
// TODO 正确实现武器创建
return new VehicleWeapon[][]{
new VehicleWeapon[]{
new VehicleWeapon().sound(ModSounds.INTO_MISSILE.get()),
new VehicleWeapon().sound(ModSounds.INTO_CANNON.get()),
},
new VehicleWeapon[]{
new VehicleWeapon(),
}
};
}
@Override
protected void defineSynchedData() {
super.defineSynchedData();
@ -121,8 +134,6 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
this.entityData.define(LOADED_AMMO, 0);
this.entityData.define(FIRE_ANIM, 0);
this.entityData.define(DELTA_ROT, 0f);
this.entityData.define(WEAPON_TYPE, 0);
this.entityData.define(PASSENGER_WEAPON_TYPE, 0);
this.entityData.define(TRACK_L, 0f);
this.entityData.define(TRACK_R, 0f);
this.entityData.define(YAW, 0f);
@ -147,7 +158,7 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
}
@Override
public Packet<ClientGamePacketListener> getAddEntityPacket() {
public @NotNull Packet<ClientGamePacketListener> getAddEntityPacket() {
return NetworkHooks.getEntitySpawningPacket(this);
}
@ -173,7 +184,7 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
}
@Override
protected void playStepSound(BlockPos pPos, BlockState pState) {
protected void playStepSound(@NotNull BlockPos pPos, @NotNull BlockState pState) {
this.playSound(ModSounds.BMP_STEP.get(), Mth.abs(this.entityData.get(POWER)) * 8, random.nextFloat() * 0.15f + 1f);
}
@ -929,18 +940,9 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
@Override
public void changeWeapon(int index, int value, boolean isScroll) {
WeaponVehicleEntity.super.changeWeapon(index, value, isScroll);
if (index != 0) return;
var type = isScroll ? (value + getWeaponType(0) + 2) % 2 : value;
var sound = switch (type) {
case 0 -> ModSounds.INTO_MISSILE.get();
case 1 -> ModSounds.INTO_CANNON.get();
default -> null;
};
if (sound == null) return;
setWeaponType(0, type);
if (entityData.get(LOADED_AMMO) > 0) {
if (this.getFirstPassenger() instanceof Player player && !player.getInventory().hasAnyMatching(s -> s.is(ModItems.CREATIVE_AMMO_BOX.get()))) {
this.insertItem(getCurrentAmmoItem(), 1);
@ -954,24 +956,6 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
var clientboundstopsoundpacket = new ClientboundStopSoundPacket(ModSounds.YX_100_RELOAD.get().getLocation(), SoundSource.PLAYERS);
player.connection.send(clientboundstopsoundpacket);
}
this.level().playSound(null, this, sound, this.getSoundSource(), 1, 1);
}
@Override
public int getWeaponType(int index) {
return switch (index) {
case 0 -> entityData.get(WEAPON_TYPE);
case 1 -> entityData.get(PASSENGER_WEAPON_TYPE);
default -> -1;
};
}
@Override
public void setWeaponType(int index, int type) {
switch (index) {
case 0 -> entityData.set(WEAPON_TYPE, type);
case 1 -> entityData.set(PASSENGER_WEAPON_TYPE, type);
}
}
@Override

View file

@ -4,10 +4,8 @@ import com.atsuishio.superbwarfare.ModUtils;
import com.atsuishio.superbwarfare.config.server.VehicleConfig;
import com.atsuishio.superbwarfare.entity.vehicle.DroneEntity;
import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModifier;
import com.atsuishio.superbwarfare.init.ModDamageTypes;
import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModParticleTypes;
import com.atsuishio.superbwarfare.init.ModSounds;
import com.atsuishio.superbwarfare.entity.vehicle.weapon.VehicleWeapon;
import com.atsuishio.superbwarfare.init.*;
import com.atsuishio.superbwarfare.item.ContainerBlockItem;
import com.atsuishio.superbwarfare.network.message.ClientIndicatorMessage;
import com.atsuishio.superbwarfare.tools.EntityFindUtil;
@ -16,6 +14,7 @@ import com.atsuishio.superbwarfare.tools.VectorTool;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.mojang.math.Axis;
import it.unimi.dsi.fastutil.ints.IntList;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.particles.ParticleTypes;
@ -67,6 +66,10 @@ public abstract class VehicleEntity extends Entity {
protected static final EntityDataAccessor<String> LAST_ATTACKER_UUID = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.STRING);
protected static final EntityDataAccessor<String> LAST_DRIVER_UUID = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.STRING);
protected static final EntityDataAccessor<IntList> SELECTED_WEAPON = SynchedEntityData.defineId(VehicleEntity.class, ModSerializers.INT_LIST_SERIALIZER.get());
public VehicleWeapon[][] availableWeapons;
protected int interpolationSteps;
protected double x;
protected double y;
@ -230,6 +233,21 @@ public abstract class VehicleEntity extends Entity {
this.entityData.define(HEALTH, this.getMaxHealth());
this.entityData.define(LAST_ATTACKER_UUID, "undefined");
this.entityData.define(LAST_DRIVER_UUID, "undefined");
if (this instanceof WeaponVehicleEntity weaponVehicle) {
this.availableWeapons = new VehicleWeapon[this.getMaxPassengers()][];
var weapons = weaponVehicle.getAllWeapons();
for (int i = 0; i < weapons.length || i < this.getMaxPassengers(); i++) {
this.availableWeapons[i] = weapons[i];
}
var selected = new int[this.getMaxPassengers()];
for (int i = 0; i < this.getMaxPassengers(); i++) {
selected[i] = weaponVehicle.hasWeapon(i) ? 0 : -1;
}
this.entityData.define(SELECTED_WEAPON, IntList.of(selected));
}
}
@Override
@ -237,6 +255,11 @@ public abstract class VehicleEntity extends Entity {
this.entityData.set(LAST_ATTACKER_UUID, compound.getString("LastAttacker"));
this.entityData.set(LAST_DRIVER_UUID, compound.getString("LastDriver"));
this.entityData.set(HEALTH, compound.getFloat("Health"));
if (this instanceof WeaponVehicleEntity) {
var selected = compound.getIntArray("SelectedWeapon");
this.entityData.set(SELECTED_WEAPON, IntList.of(selected));
}
}
@Override
@ -244,6 +267,10 @@ public abstract class VehicleEntity extends Entity {
compound.putFloat("Health", this.entityData.get(HEALTH));
compound.putString("LastAttacker", this.entityData.get(LAST_ATTACKER_UUID));
compound.putString("LastDriver", this.entityData.get(LAST_DRIVER_UUID));
if (this instanceof WeaponVehicleEntity) {
compound.putIntArray("SelectedWeapon", this.entityData.get(SELECTED_WEAPON).toIntArray());
}
}
@Override

View file

@ -1,5 +1,10 @@
package com.atsuishio.superbwarfare.entity.vehicle.base;
import com.atsuishio.superbwarfare.entity.vehicle.weapon.VehicleWeapon;
import it.unimi.dsi.fastutil.ints.IntList;
import java.util.List;
/**
* 拥有任意武器的载具
*/
@ -11,7 +16,11 @@ public interface WeaponVehicleEntity extends ArmedVehicleEntity {
* @return 武器是否可用
*/
default boolean hasWeapon(int index) {
return getWeaponType(index) != -1;
if (!(this instanceof VehicleEntity vehicle)) return false;
if (index < 0 || index >= vehicle.getMaxPassengers()) return false;
var weapons = getAvailableWeapons(index);
return !weapons.isEmpty();
}
/**
@ -22,6 +31,73 @@ public interface WeaponVehicleEntity extends ArmedVehicleEntity {
* @param isScroll 是否是滚动事件
*/
default void changeWeapon(int index, int value, boolean isScroll) {
if (!(this instanceof VehicleEntity vehicle)) return;
if (index < 0 || index >= vehicle.getMaxPassengers()) return;
var weapons = getAvailableWeapons(index);
if (weapons.isEmpty()) return;
var count = weapons.size();
var typeIndex = isScroll ? (value + getWeaponType(index) + count) % count : value;
var weapon = weapons.get(typeIndex);
// 修改该槽位选择的武器
setWeaponType(index, typeIndex);
// 播放武器切换音效
var sound = weapon.sound;
if (sound != null) {
vehicle.level().playSound(null, vehicle, sound, vehicle.getSoundSource(), 1, 1);
}
}
/**
* 获取所有可用武器列表
*/
default VehicleWeapon[][] getAllWeapons() {
return new VehicleWeapon[0][];
}
/**
* 获取该槽位可用的武器列表
*
* @param index 武器槽位
*/
default List<VehicleWeapon> getAvailableWeapons(int index) {
if (!(this instanceof VehicleEntity vehicle)) return List.of();
if (index < 0 || index >= vehicle.getMaxPassengers()) return List.of();
if (vehicle.availableWeapons[index] != null) {
return List.of(vehicle.availableWeapons[index]);
}
return List.of();
}
default VehicleWeapon[][] initAvailableWeapons() {
if (!(this instanceof VehicleEntity vehicle)) return null;
if (vehicle.availableWeapons == null) {
vehicle.availableWeapons = new VehicleWeapon[vehicle.getMaxPassengers()][];
}
return vehicle.availableWeapons;
}
/**
* 获取该槽位当前的武器
*
* @param index 武器槽位
*/
default VehicleWeapon getWeapon(int index) {
if (!(this instanceof VehicleEntity vehicle)) return null;
if (index < 0 || index >= vehicle.getMaxPassengers()) return null;
var weapons = getAvailableWeapons(index);
if (weapons.isEmpty()) return null;
var type = getWeaponType(index);
if (type < 0 || type >= weapons.size()) return null;
return weapons.get(type);
}
/**
@ -31,8 +107,12 @@ public interface WeaponVehicleEntity extends ArmedVehicleEntity {
* @return 武器类型
*/
default int getWeaponType(int index) {
// 默认认为只有第一个位置拥有一个武器
return index == 0 ? 0 : -1;
if (!(this instanceof VehicleEntity vehicle)) return -1;
var selectedWeapons = vehicle.getEntityData().get(VehicleEntity.SELECTED_WEAPON);
if (selectedWeapons.size() <= index) return -1;
return selectedWeapons.getInt(index);
}
/**
@ -42,5 +122,10 @@ public interface WeaponVehicleEntity extends ArmedVehicleEntity {
* @param type 武器类型
*/
default void setWeaponType(int index, int type) {
if (!(this instanceof VehicleEntity vehicle)) return;
var selectedWeapons = vehicle.getEntityData().get(VehicleEntity.SELECTED_WEAPON).toIntArray();
selectedWeapons[index] = type;
vehicle.getEntityData().set(VehicleEntity.SELECTED_WEAPON, IntList.of(selectedWeapons));
}
}

View file

@ -2,6 +2,7 @@ package com.atsuishio.superbwarfare.entity.vehicle.weapon;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.item.ItemStack;
public class VehicleWeapon {
@ -21,6 +22,8 @@ public class VehicleWeapon {
// 备弹量
public int backupAmmo;
public SoundEvent sound;
public VehicleWeapon icon(ResourceLocation icon) {
this.icon = icon;
return this;
@ -48,6 +51,16 @@ public class VehicleWeapon {
return this;
}
/**
* 切换到该武器时的音效
*
* @param sound 音效
*/
public VehicleWeapon sound(SoundEvent sound) {
this.sound = sound;
return this;
}
/**
* 载具武器的装弹类型
* INDIRECT - 需要先进行上弹再发射
@ -55,7 +68,7 @@ public class VehicleWeapon {
*/
public enum AmmoType {
INDIRECT,
DIRECT
DIRECT,
}
public VehicleWeapon maxAmmo(int maxAmmo) {