添加激光防御塔

This commit is contained in:
Atsuihsio 2025-02-11 22:18:16 +08:00
parent fd660f6b8d
commit ccd74099dd
17 changed files with 2989 additions and 4 deletions

View file

@ -1,5 +1,6 @@
package com.atsuishio.superbwarfare.block;
import com.atsuishio.superbwarfare.entity.vehicle.VehicleEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.Registries;
@ -7,7 +8,6 @@ import net.minecraft.network.chat.Component;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.DamageTypes;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.context.BlockPlaceContext;
@ -93,9 +93,9 @@ public class BarbedWireBlock extends Block {
public void entityInside(BlockState blockstate, Level world, BlockPos pos, Entity entity) {
super.entityInside(blockstate, world, pos, entity);
if (entity instanceof LivingEntity living) {
living.makeStuckInBlock(Blocks.AIR.defaultBlockState(), new Vec3(0.25, 0.05, 0.25));
living.hurt(new DamageSource(world.registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.CACTUS)), 1);
if (!(entity instanceof VehicleEntity)) {
entity.makeStuckInBlock(Blocks.AIR.defaultBlockState(), new Vec3(0.15, 0.04, 0.15));
entity.hurt(new DamageSource(world.registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.CACTUS)), 2);
}
}
}

View file

@ -0,0 +1,28 @@
package com.atsuishio.superbwarfare.client.layer;
import com.atsuishio.superbwarfare.ModUtils;
import com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.resources.ResourceLocation;
import software.bernie.geckolib.cache.object.BakedGeoModel;
import software.bernie.geckolib.renderer.GeoRenderer;
import software.bernie.geckolib.renderer.layer.GeoRenderLayer;
public class LaserTowerLaserLayer extends GeoRenderLayer<LaserTowerEntity> {
private static final ResourceLocation LAYER = ModUtils.loc("textures/entity/laser_tower_laser.png");
public LaserTowerLaserLayer(GeoRenderer<LaserTowerEntity> entityRenderer) {
super(entityRenderer);
}
@Override
public void render(PoseStack poseStack, LaserTowerEntity animatable, BakedGeoModel bakedModel, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, float partialTick, int packedLight, int packedOverlay) {
RenderType glowRenderType = RenderType.energySwirl(LAYER, 1, 1);
getRenderer().reRender(getDefaultBakedModel(animatable), poseStack, bufferSource, animatable, glowRenderType, bufferSource.getBuffer(glowRenderType), partialTick, packedLight, OverlayTexture.NO_OVERLAY, 1, 1, 1, 1);
}
}

View file

@ -0,0 +1,31 @@
package com.atsuishio.superbwarfare.client.layer;
import com.atsuishio.superbwarfare.ModUtils;
import com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.resources.ResourceLocation;
import software.bernie.geckolib.cache.object.BakedGeoModel;
import software.bernie.geckolib.renderer.GeoRenderer;
import software.bernie.geckolib.renderer.layer.GeoRenderLayer;
import static com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity.ACTIVE;
public class LaserTowerPowerLayer extends GeoRenderLayer<LaserTowerEntity> {
private static final ResourceLocation LAYER = ModUtils.loc("textures/entity/laser_tower_e.png");
public LaserTowerPowerLayer(GeoRenderer<LaserTowerEntity> entityRenderer) {
super(entityRenderer);
}
@Override
public void render(PoseStack poseStack, LaserTowerEntity animatable, BakedGeoModel bakedModel, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, float partialTick, int packedLight, int packedOverlay) {
if (animatable.getEnergy() <= 0 || !animatable.getEntityData().get(ACTIVE)) return;
RenderType glowRenderType = RenderType.eyes(LAYER);
getRenderer().reRender(getDefaultBakedModel(animatable), poseStack, bufferSource, animatable, glowRenderType, bufferSource.getBuffer(glowRenderType), partialTick, packedLight, OverlayTexture.NO_OVERLAY, 1, 1, 1, 1);
}
}

View file

@ -0,0 +1,34 @@
package com.atsuishio.superbwarfare.client.model.entity;
import com.atsuishio.superbwarfare.ModUtils;
import com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity;
import net.minecraft.resources.ResourceLocation;
import software.bernie.geckolib.core.animatable.model.CoreGeoBone;
import software.bernie.geckolib.core.animation.AnimationState;
import software.bernie.geckolib.model.GeoModel;
import static com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity.LASER_LENGTH;
public class LaserTowerModel extends GeoModel<LaserTowerEntity> {
@Override
public ResourceLocation getAnimationResource(LaserTowerEntity entity) {
return ModUtils.loc("animations/laser_tower.animation.json");
}
@Override
public ResourceLocation getModelResource(LaserTowerEntity entity) {
return ModUtils.loc("geo/laser_tower.geo.json");
}
@Override
public ResourceLocation getTextureResource(LaserTowerEntity entity) {
return ModUtils.loc("textures/entity/laser_tower.png");
}
@Override
public void setCustomAnimations(LaserTowerEntity animatable, long instanceId, AnimationState<LaserTowerEntity> animationState) {
CoreGeoBone laser = getAnimationProcessor().getBone("laser");
laser.setScaleZ(10 * animatable.getEntityData().get(LASER_LENGTH));
}
}

View file

@ -0,0 +1,59 @@
package com.atsuishio.superbwarfare.client.renderer.entity;
import com.atsuishio.superbwarfare.client.layer.LaserTowerLaserLayer;
import com.atsuishio.superbwarfare.client.layer.LaserTowerPowerLayer;
import com.atsuishio.superbwarfare.client.model.entity.LaserTowerModel;
import com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import software.bernie.geckolib.cache.object.BakedGeoModel;
import software.bernie.geckolib.cache.object.GeoBone;
import software.bernie.geckolib.renderer.GeoEntityRenderer;
public class LaserTowerRenderer extends GeoEntityRenderer<LaserTowerEntity> {
public LaserTowerRenderer(EntityRendererProvider.Context renderManager) {
super(renderManager, new LaserTowerModel());
this.addRenderLayer(new LaserTowerPowerLayer(this));
this.addRenderLayer(new LaserTowerLaserLayer(this));
}
@Override
public RenderType getRenderType(LaserTowerEntity animatable, ResourceLocation texture, MultiBufferSource bufferSource, float partialTick) {
return RenderType.entityTranslucent(getTextureLocation(animatable));
}
@Override
public void preRender(PoseStack poseStack, LaserTowerEntity entity, BakedGeoModel model, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, float red, float green,
float blue, float alpha) {
float scale = 1f;
this.scaleHeight = scale;
this.scaleWidth = scale;
super.preRender(poseStack, entity, model, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha);
}
@Override
public void render(LaserTowerEntity entityIn, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource bufferIn, int packedLightIn) {
poseStack.pushPose();
super.render(entityIn, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn);
poseStack.popPose();
}
@Override
public void renderRecursively(PoseStack poseStack, LaserTowerEntity animatable, GeoBone bone, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
String name = bone.getName();
if (name.equals("turret")) {
bone.setRotY(-Mth.lerp(partialTick, animatable.yRotO, animatable.getYRot()) * Mth.DEG_TO_RAD);
}
if (name.equals("barrel")) {
bone.setRotX(-Mth.lerp(partialTick, animatable.xRotO, animatable.getXRot()) * Mth.DEG_TO_RAD);
}
super.renderRecursively(poseStack, animatable, bone, renderType, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha);
}
}

View file

@ -0,0 +1,341 @@
package com.atsuishio.superbwarfare.entity.vehicle;
import com.atsuishio.superbwarfare.init.*;
import com.atsuishio.superbwarfare.item.ContainerBlockItem;
import com.atsuishio.superbwarfare.tools.CustomExplosion;
import com.atsuishio.superbwarfare.tools.EntityFindUtil;
import com.atsuishio.superbwarfare.tools.ParticleTool;
import com.atsuishio.superbwarfare.tools.VectorTool;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.players.OldUsersConverter;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.DamageTypes;
import net.minecraft.world.entity.*;
import net.minecraft.world.entity.monster.Monster;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.network.NetworkHooks;
import net.minecraftforge.network.PlayMessages;
import org.joml.Math;
import software.bernie.geckolib.animatable.GeoEntity;
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.core.animation.AnimatableManager;
import software.bernie.geckolib.core.animation.AnimationController;
import software.bernie.geckolib.core.animation.AnimationState;
import software.bernie.geckolib.core.animation.RawAnimation;
import software.bernie.geckolib.core.object.PlayState;
import software.bernie.geckolib.util.GeckoLibUtil;
import java.util.Comparator;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.StreamSupport;
import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle;
public class LaserTowerEntity extends EnergyVehicleEntity implements GeoEntity, OwnableEntity {
public static final EntityDataAccessor<Integer> COOL_DOWN = SynchedEntityData.defineId(LaserTowerEntity.class, EntityDataSerializers.INT);
public static final EntityDataAccessor<Boolean> ACTIVE = SynchedEntityData.defineId(LaserTowerEntity.class, EntityDataSerializers.BOOLEAN);
public static final EntityDataAccessor<Optional<UUID>> OWNER_UUID = SynchedEntityData.defineId(LaserTowerEntity.class, EntityDataSerializers.OPTIONAL_UUID);
public static final EntityDataAccessor<Float> LASER_LENGTH = SynchedEntityData.defineId(LaserTowerEntity.class, EntityDataSerializers.FLOAT);
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
public static final float MAX_HEALTH = 100;
public static final int MAX_ENERGY = 500000;
public static final int SHOOT_COST = 5000;
public LaserTowerEntity(PlayMessages.SpawnEntity packet, Level world) {
this(ModEntities.LASER_TOWER.get(), world);
}
public LaserTowerEntity(EntityType<LaserTowerEntity> type, Level world) {
super(type, world);
this.noCulling = true;
}
public LaserTowerEntity(LivingEntity owner, Level level) {
super(ModEntities.CLAYMORE.get(), level);
this.setOwnerUUID(owner.getUUID());
}
public boolean isOwnedBy(LivingEntity pEntity) {
return pEntity == this.getOwner();
}
@Override
protected void defineSynchedData() {
super.defineSynchedData();
this.entityData.define(OWNER_UUID, Optional.empty());
this.entityData.define(COOL_DOWN, 0);
this.entityData.define(LASER_LENGTH, 0f);
this.entityData.define(ACTIVE, false);
}
@Override
public void addAdditionalSaveData(CompoundTag compound) {
super.addAdditionalSaveData(compound);
compound.putInt("CoolDown", this.entityData.get(COOL_DOWN));
compound.putBoolean("Active", this.entityData.get(ACTIVE));
if (this.getOwnerUUID() != null) {
compound.putUUID("Owner", this.getOwnerUUID());
}
}
@Override
public void readAdditionalSaveData(CompoundTag compound) {
super.readAdditionalSaveData(compound);
this.entityData.set(COOL_DOWN, compound.getInt("CoolDown"));
this.entityData.set(ACTIVE, compound.getBoolean("Active"));
UUID uuid;
if (compound.hasUUID("Owner")) {
uuid = compound.getUUID("Owner");
} else {
String s = compound.getString("Owner");
assert this.getServer() != null;
uuid = OldUsersConverter.convertMobOwnerIfNecessary(this.getServer(), s);
}
if (uuid != null) {
try {
this.setOwnerUUID(uuid);
} catch (Throwable ignored) {
}
}
}
public void setOwnerUUID(@javax.annotation.Nullable UUID pUuid) {
this.entityData.set(OWNER_UUID, Optional.ofNullable(pUuid));
}
@javax.annotation.Nullable
public UUID getOwnerUUID() {
return this.entityData.get(OWNER_UUID).orElse(null);
}
@Override
public Packet<ClientGamePacketListener> getAddEntityPacket() {
return NetworkHooks.getEntitySpawningPacket(this);
}
@Override
public boolean hurt(DamageSource source, float amount) {
super.hurt(source, amount);
if (this.level() instanceof ServerLevel serverLevel) {
sendParticle(serverLevel, ModParticleTypes.FIRE_STAR.get(), this.getX(), this.getY() + 2.5, this.getZ(), 4, 0.2, 0.2, 0.2, 0.2, false);
}
if (source.is(DamageTypes.ARROW)) {
amount *= 0.1f;
}
if (source.is(DamageTypes.TRIDENT)) {
amount *= 0.2f;
}
if (source.is(DamageTypes.MOB_ATTACK)) {
amount *= 0.2f;
}
if (source.is(DamageTypes.MOB_ATTACK_NO_AGGRO)) {
amount *= 0.2f;
}
if (source.is(DamageTypes.MOB_PROJECTILE)) {
amount *= 0.4f;
}
if (source.is(DamageTypes.PLAYER_ATTACK)) {
amount *= 0.4f;
}
if (source.is(DamageTypes.LAVA)) {
amount *= 1f;
}
if (source.is(DamageTypes.EXPLOSION)) {
amount *= 1.5f;
}
if (source.is(DamageTypes.PLAYER_EXPLOSION)) {
amount *= 1.5f;
}
if (source.is(ModDamageTypes.CUSTOM_EXPLOSION)) {
amount *= 0.5f;
}
if (source.is(ModDamageTypes.PROJECTILE_BOOM)) {
amount *= 0.5f;
}
if (source.is(ModDamageTypes.MINE)) {
amount *= 0.5f;
}
if (source.is(ModDamageTypes.LUNGE_MINE)) {
amount *= 0.5f;
}
if (source.is(ModDamageTypes.CANNON_FIRE)) {
amount *= 0.6f;
}
if (source.is(ModTags.DamageTypes.PROJECTILE)) {
amount *= 0.08f;
}
if (source.is(ModTags.DamageTypes.PROJECTILE_ABSOLUTE)) {
amount *= 0.5f;
}
if (source.is(ModDamageTypes.VEHICLE_STRIKE)) {
amount *= 5f;
}
this.level().playSound(null, this.getOnPos(), ModSounds.HIT.get(), SoundSource.PLAYERS, 1, 1);
this.hurt(Math.max(amount - 2, 0), source.getEntity(), false);
return true;
}
@Override
public InteractionResult interact(Player player, InteractionHand hand) {
ItemStack stack = player.getMainHandItem();
if (player.isCrouching()) {
if (stack.is(ModItems.CROWBAR.get())) {
ItemStack container = ContainerBlockItem.createInstance(this);
if (!player.addItem(container)) {
player.drop(container, false);
}
this.remove(RemovalReason.DISCARDED);
this.discard();
return InteractionResult.SUCCESS;
} else if (!entityData.get(ACTIVE)) {
entityData.set(ACTIVE, true);
this.setOwnerUUID(player.getUUID());
if (player instanceof ServerPlayer serverPlayer) {
serverPlayer.level().playSound(null, serverPlayer.getOnPos(), SoundEvents.ARROW_HIT_PLAYER, SoundSource.PLAYERS, 0.5F, 1);
}
return InteractionResult.sidedSuccess(this.level().isClientSide());
}
}
return InteractionResult.sidedSuccess(this.level().isClientSide());
}
@Override
public Vec3 getDeltaMovement() {
return new Vec3(0, Math.min(super.getDeltaMovement().y, 0), 0);
}
@Override
public void baseTick() {
super.baseTick();
if (this.entityData.get(COOL_DOWN) > 0) {
this.entityData.set(COOL_DOWN, this.entityData.get(COOL_DOWN) - 1);
}
this.move(MoverType.SELF, this.getDeltaMovement());
if (this.onGround()) {
this.setDeltaMovement(Vec3.ZERO);
} else {
this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.04, 0.0));
}
autoAim();
this.refreshDimensions();
}
@Override
public void destroy() {
Entity attacker = EntityFindUtil.findEntity(this.level(), this.entityData.get(LAST_ATTACKER_UUID));
if (level() instanceof ServerLevel) {
CustomExplosion explosion = new CustomExplosion(this.level(), this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), attacker, attacker), 10f,
this.getX(), this.getY(), this.getZ(), 3f, Explosion.BlockInteraction.KEEP).setDamageMultiplier(1);
explosion.explode();
net.minecraftforge.event.ForgeEventFactory.onExplosionStart(this.level(), explosion);
explosion.finalizeExplosion(false);
ParticleTool.spawnMediumExplosionParticles(this.level(), this.position());
}
this.discard();
}
public void autoAim() {
if (this.entityData.get(ENERGY) <= 0 || !entityData.get(ACTIVE) || this.entityData.get(COOL_DOWN) > 10) return;
Entity naerestEntity = seekNearLivingEntity(80);
if (naerestEntity != null) {
Vec3 barrelRootPos = new Vec3(this.getX(), this.getY() + 1.390625f, this.getZ());
Vec3 targetVec = barrelRootPos.vectorTo(naerestEntity.getEyePosition()).normalize();
double d0 = targetVec.x;
double d1 = targetVec.y;
double d2 = targetVec.z;
double d3 = Math.sqrt(d0 * d0 + d2 * d2);
this.setXRot(Mth.clamp(Mth.wrapDegrees((float) (-(Mth.atan2(d1, d3) * 57.2957763671875))), -90, 40));
float targetY = Mth.wrapDegrees((float) (Mth.atan2(d2, d0) * 57.2957763671875) - 90.0F);
float diffY = Math.clamp(-90f, 90f, Mth.wrapDegrees(targetY - this.getYRot()));
this.setYRot(this.getYRot() + Mth.clamp(0.5f * diffY, -25f, 25f));
this.setRot(this.getYRot(), this.getXRot());
if (this.entityData.get(COOL_DOWN) == 0 && VectorTool.calculateAngle(getViewVector(1), targetVec) < 1) {
if (level() instanceof ServerLevel) {
this.level().playSound(this, getOnPos(), ModSounds.CHARGE_RIFLE_FIRE_BOOM_3P.get(), SoundSource.PLAYERS, 2, 1);
}
naerestEntity.hurt(ModDamageTypes.causeLaserDamage(this.level().registryAccess(), getOwner(), getOwner()), (float) 25);
naerestEntity.invulnerableTime = 0;
entityData.set(LASER_LENGTH, distanceTo(naerestEntity));
this.entityData.set(COOL_DOWN, 20);
this.consumeEnergy(SHOOT_COST);
}
}
}
public Entity seekNearLivingEntity(double seekRange) {
return StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false)
.filter(e -> {
// TODO 自定义目标列表
if (e.distanceTo(this) <= seekRange && e instanceof Monster) {
return level().clip(new ClipContext(this.getEyePosition(), e.getEyePosition(),
ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() != HitResult.Type.BLOCK;
}
return false;
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
}
private PlayState movementPredicate(AnimationState<LaserTowerEntity> event) {
if (this.entityData.get(COOL_DOWN) > 10) {
return event.setAndContinue(RawAnimation.begin().thenPlay("animation.lt.fire"));
}
return event.setAndContinue(RawAnimation.begin().thenLoop("animation.lt.idle"));
}
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar data) {
data.add(new AnimationController<>(this, "movement", 0, this::movementPredicate));
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.cache;
}
@Override
public int getMaxEnergy() {
return MAX_ENERGY;
}
@Override
public float getMaxHealth() {
return MAX_HEALTH;
}
}

View file

@ -86,6 +86,8 @@ public class ModEntities {
EntityType.Builder.<Bmp2Entity>of(Bmp2Entity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(Bmp2Entity::new).fireImmune().sized(4f, 3f));
public static final RegistryObject<EntityType<WgMissileEntity>> WG_MISSILE = register("wg_missile",
EntityType.Builder.<WgMissileEntity>of(WgMissileEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(WgMissileEntity::new).fireImmune().sized(0.5f, 0.5f));
public static final RegistryObject<EntityType<LaserTowerEntity>> LASER_TOWER = register("laser_tower",
EntityType.Builder.<LaserTowerEntity>of(LaserTowerEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(LaserTowerEntity::new).fireImmune().sized(0.9f, 1.65f));
private static <T extends Entity> RegistryObject<EntityType<T>> register(String name, EntityType.Builder<T> entityTypeBuilder) {
return REGISTRY.register(name, () -> entityTypeBuilder.build(name));

View file

@ -41,5 +41,6 @@ public class ModEntityRenderers {
event.registerEntityRenderer(ModEntities.MELON_BOMB.get(), MelonBombEntityRenderer::new);
event.registerEntityRenderer(ModEntities.BMP_2.get(), Bmp2Renderer::new);
event.registerEntityRenderer(ModEntities.WG_MISSILE.get(), WgMissileRenderer::new);
event.registerEntityRenderer(ModEntities.LASER_TOWER.get(), LaserTowerRenderer::new);
}
}

View file

@ -106,6 +106,7 @@ public class ModTabs {
output.accept(ContainerBlockItem.createInstance(ModEntities.MK_42.get()));
output.accept(ContainerBlockItem.createInstance(ModEntities.MLE_1934.get()));
output.accept(ContainerBlockItem.createInstance(ModEntities.ANNIHILATOR.get()));
output.accept(ContainerBlockItem.createInstance(ModEntities.LASER_TOWER.get()));
output.accept(ContainerBlockItem.createInstance(ModEntities.SPEEDBOAT.get(), true));
output.accept(ContainerBlockItem.createInstance(ModEntities.AH_6.get()));
output.accept(ContainerBlockItem.createInstance(ModEntities.LAV_150.get(),true));

View file

@ -0,0 +1,28 @@
{
"format_version": "1.8.0",
"animations": {
"animation.lt.fire": {
"loop": "hold_on_last_frame",
"animation_length": 1,
"bones": {
"laser": {
"scale": {
"0.0": [0, 0, 1],
"0.0083": [1.3, 1.3, 1],
"0.1333": [1.3, 1.3, 1],
"0.2667": [0, 0, 1],
"0.9917": [0, 0, 1]
}
}
}
},
"animation.lt.idle": {
"loop": true,
"bones": {
"laser": {
"scale": [0, 0, 1]
}
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -406,6 +406,7 @@
"entity.superbwarfare.melon_bomb": "Melon Bomb",
"entity.superbwarfare.bmp_2": "BMP-2",
"entity.superbwarfare.wg_missile": "Wire Guide Missile",
"entity.superbwarfare.laser_tower": "Laser Defense Tower",
"key.categories.superbwarfare": "Superb Warfare",
"key.superbwarfare.hold_zoom": "Zoom(Hold)",

View file

@ -404,6 +404,7 @@
"entity.superbwarfare.melon_bomb": "西瓜航弹",
"entity.superbwarfare.bmp_2": "BMP-2 履带式步兵战车",
"entity.superbwarfare.wg_missile": "线控导弹",
"entity.superbwarfare.laser_tower": "激光防御塔",
"key.categories.superbwarfare": "卓越前线",
"key.superbwarfare.hold_zoom": "瞄准(按住)",

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,31 @@
{
"type": "minecraft:crafting_shaped",
"category": "misc",
"pattern": [
" a ",
" b ",
"dcd"
],
"key": {
"a": {
"item": "minecraft:beacon"
},
"b": {
"item": "superbwarfare:motor"
},
"c": {
"item": "superbwarfare:cell"
},
"d": {
"item": "minecraft:iron_ingot"
}
},
"result": {
"item": "superbwarfare:container",
"nbt": {
"BlockEntityTag": {
"EntityType": "superbwarfare:laser_tower"
}
}
}
}