Merge branch 'refs/heads/superbwarfare' into superbwarfare_c4
# Conflicts: # src/main/java/com/atsuishio/superbwarfare/entity/DroneEntity.java
This commit is contained in:
commit
87b82ca209
29 changed files with 1836 additions and 94 deletions
|
@ -13,5 +13,5 @@ mod_description=A Warfare Mod
|
|||
minecraft_version=1.20.1
|
||||
jei_version=15.2.0.27
|
||||
cloth_config_version=11.1.106
|
||||
mod_version=0.4.0
|
||||
mod_version=0.4.2
|
||||
mod_authors=Atsuishio, Roki27, Light_Quanta
|
|
@ -18,6 +18,7 @@ import net.minecraft.world.level.Level;
|
|||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.joml.Math;
|
||||
import software.bernie.geckolib.animatable.GeoBlockEntity;
|
||||
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
|
||||
import software.bernie.geckolib.core.animation.AnimatableManager;
|
||||
|
@ -54,12 +55,12 @@ public class ContainerBlockEntity extends BlockEntity implements GeoBlockEntity
|
|||
}
|
||||
} else {
|
||||
if (blockEntity.entity != null) {
|
||||
blockEntity.entity.setPos(pPos.getX() + 0.5, pPos.getY() + 0.5, pPos.getZ() + 0.5);
|
||||
blockEntity.entity.setPos(pPos.getX() + 0.5 + (2 * Math.random() - 1) * 0.1f, pPos.getY() + 0.5 + (2 * Math.random() - 1) * 0.1f, pPos.getZ() + 0.5 + (2 * Math.random() - 1) * 0.1f);
|
||||
pLevel.addFreshEntity(blockEntity.entity);
|
||||
} else if (blockEntity.entityType != null) {
|
||||
var entity = blockEntity.entityType.create(pLevel);
|
||||
if (entity != null) {
|
||||
entity.setPos(pPos.getX() + 0.5, pPos.getY() + 0.5, pPos.getZ() + 0.5);
|
||||
entity.setPos(pPos.getX() + 0.5 + (2 * Math.random() - 1) * 0.1f, pPos.getY() + 0.5 + (2 * Math.random() - 1) * 0.1f, pPos.getZ() + 0.5 + (2 * Math.random() - 1) * 0.1f);
|
||||
pLevel.addFreshEntity(entity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package com.atsuishio.superbwarfare.client.model.entity;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.Tom6Entity;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import software.bernie.geckolib.model.GeoModel;
|
||||
|
||||
public class Tom6Model extends GeoModel<Tom6Entity> {
|
||||
|
||||
@Override
|
||||
public ResourceLocation getAnimationResource(Tom6Entity entity) {
|
||||
return null;
|
||||
// return ModUtils.loc("animations/wheel_chair.animation.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getModelResource(Tom6Entity entity) {
|
||||
return ModUtils.loc("geo/tom_6.geo.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureResource(Tom6Entity entity) {
|
||||
return ModUtils.loc("textures/entity/tom_6.png");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.atsuishio.superbwarfare.client.renderer.entity;
|
||||
|
||||
import com.atsuishio.superbwarfare.entity.projectile.MelonBombEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Axis;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.client.renderer.entity.TntMinecartRenderer;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
|
||||
public class MelonBombEntityRenderer extends EntityRenderer<MelonBombEntity> {
|
||||
|
||||
private final BlockRenderDispatcher blockRenderer;
|
||||
|
||||
public MelonBombEntityRenderer(EntityRendererProvider.Context context) {
|
||||
super(context);
|
||||
this.shadowRadius = 0.2f;
|
||||
this.blockRenderer = context.getBlockRenderDispatcher();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MelonBombEntity entity, float entityYaw, float partialTicks, PoseStack matrixStack, MultiBufferSource buffer, int packedLight) {
|
||||
matrixStack.pushPose();
|
||||
matrixStack.translate(0.0, 0.5, 0.0);
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(-90.0f));
|
||||
matrixStack.translate(-0.5, -0.5, 0.5);
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(90.0f));
|
||||
TntMinecartRenderer.renderWhiteSolidBlock(this.blockRenderer, Blocks.MELON.defaultBlockState(), matrixStack, buffer, packedLight, false);
|
||||
matrixStack.popPose();
|
||||
super.render(entity, entityYaw, partialTicks, matrixStack, buffer, packedLight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureLocation(MelonBombEntity entity) {
|
||||
return TextureAtlas.LOCATION_BLOCKS;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package com.atsuishio.superbwarfare.client.renderer.entity;
|
||||
|
||||
import com.atsuishio.superbwarfare.client.model.entity.Tom6Model;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.Tom6Entity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Axis;
|
||||
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;
|
||||
|
||||
import static com.atsuishio.superbwarfare.entity.vehicle.Tom6Entity.MELON;
|
||||
|
||||
public class Tom6Renderer extends GeoEntityRenderer<Tom6Entity> {
|
||||
|
||||
public Tom6Renderer(EntityRendererProvider.Context renderManager) {
|
||||
super(renderManager, new Tom6Model());
|
||||
this.shadowRadius = 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderType getRenderType(Tom6Entity animatable, ResourceLocation texture, MultiBufferSource bufferSource, float partialTick) {
|
||||
return RenderType.entityTranslucent(getTextureLocation(animatable));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRender(PoseStack poseStack, Tom6Entity 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(Tom6Entity entityIn, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource bufferIn, int packedLightIn) {
|
||||
poseStack.pushPose();
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(-entityYaw));
|
||||
poseStack.mulPose(Axis.XP.rotationDegrees(Mth.lerp(partialTicks, entityIn.xRotO, entityIn.getXRot())));
|
||||
poseStack.mulPose(Axis.ZP.rotationDegrees(Mth.lerp(partialTicks, entityIn.prevRoll, entityIn.getRoll())));
|
||||
super.render(entityIn, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn);
|
||||
poseStack.popPose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderRecursively(PoseStack poseStack, Tom6Entity 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("melon")) {
|
||||
bone.setHidden(!animatable.getEntityData().get(MELON));
|
||||
}
|
||||
super.renderRecursively(poseStack, animatable, bone, renderType, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import com.atsuishio.superbwarfare.init.ModEntities;
|
|||
import com.atsuishio.superbwarfare.init.ModItems;
|
||||
import com.atsuishio.superbwarfare.init.ModSounds;
|
||||
import com.atsuishio.superbwarfare.item.Monitor;
|
||||
import com.atsuishio.superbwarfare.tools.ChunkLoadTool;
|
||||
import com.atsuishio.superbwarfare.tools.CustomExplosion;
|
||||
import com.atsuishio.superbwarfare.tools.EntityFindUtil;
|
||||
import com.atsuishio.superbwarfare.tools.ParticleTool;
|
||||
|
@ -52,11 +53,10 @@ import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache
|
|||
import software.bernie.geckolib.core.animation.AnimatableManager;
|
||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
|
||||
|
||||
public static final EntityDataAccessor<Boolean> LINKED = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.BOOLEAN);
|
||||
public static final EntityDataAccessor<String> CONTROLLER = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.STRING);
|
||||
public static final EntityDataAccessor<Integer> AMMO = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.INT);
|
||||
|
@ -77,6 +77,7 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
|
|||
public double lastTickVerticalSpeed;
|
||||
public float pitch;
|
||||
public float pitchO;
|
||||
public Set<Long> loadedChunks = new HashSet<>();
|
||||
|
||||
public DroneEntity(PlayMessages.SpawnEntity packet, Level world) {
|
||||
this(ModEntities.DRONE.get(), world);
|
||||
|
@ -144,7 +145,7 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
|
|||
compound.putString("Controller", this.entityData.get(CONTROLLER));
|
||||
compound.putInt("Ammo", this.entityData.get(AMMO));
|
||||
compound.putBoolean("Kamikaze", this.entityData.get(KAMIKAZE));
|
||||
compound.putInt("Kamikaze", this.entityData.get(KAMIKAZE_MODE));
|
||||
compound.putInt("KamikazeMode", this.entityData.get(KAMIKAZE_MODE));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -170,6 +171,11 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
|
|||
|
||||
super.baseTick();
|
||||
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
// 更新需要加载的区块
|
||||
ChunkLoadTool.updateLoadedChunks(serverLevel, this, this.loadedChunks);
|
||||
}
|
||||
|
||||
lastTickSpeed = this.getDeltaMovement().length();
|
||||
lastTickVerticalSpeed = this.getDeltaMovement().y;
|
||||
|
||||
|
@ -179,9 +185,9 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
|
|||
|
||||
Player controller = EntityFindUtil.findPlayer(this.level(), this.entityData.get(CONTROLLER));
|
||||
|
||||
|
||||
if (!this.onGround()) {
|
||||
if (controller != null) {
|
||||
handleSimulationDistance(controller);
|
||||
ItemStack stack = controller.getMainHandItem();
|
||||
if (stack.is(ModItems.MONITOR.get())) {
|
||||
if (stack.getOrCreateTag().getBoolean("Using") && controller.level().isClientSide) {
|
||||
|
@ -198,6 +204,15 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
|
|||
if (!controller.level().isClientSide) {
|
||||
this.level().playSound(null, this.getOnPos(), ModSounds.DRONE_SOUND.get(), SoundSource.AMBIENT, 3, 1);
|
||||
}
|
||||
|
||||
if (tickCount % 5 == 0) {
|
||||
controller.getInventory().items.stream().filter(pStack -> pStack.getItem() == ModItems.MONITOR.get())
|
||||
.forEach(pStack -> {
|
||||
if (pStack.getOrCreateTag().getString(Monitor.LINKED_DRONE).equals(this.getStringUUID())) {
|
||||
Monitor.getDronePos(pStack, this.position());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,6 +242,25 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
|
|||
this.refreshDimensions();
|
||||
}
|
||||
|
||||
public void handleSimulationDistance(Player player) {
|
||||
if (player.level() instanceof ServerLevel serverLevel && player instanceof ServerPlayer) {
|
||||
var distanceManager = serverLevel.getChunkSource().chunkMap.getDistanceManager();
|
||||
var playerTicketManager = distanceManager.playerTicketManager;
|
||||
int maxDistance = playerTicketManager.viewDistance;
|
||||
|
||||
if (this.position().vectorTo(player.position()).horizontalDistance() > maxDistance * 16) {
|
||||
upInputDown = false;
|
||||
downInputDown = false;
|
||||
forwardInputDown = false;
|
||||
backInputDown = false;
|
||||
leftInputDown = false;
|
||||
rightInputDown = false;
|
||||
Vec3 toVec = position().vectorTo(player.position()).normalize();
|
||||
setDeltaMovement(getDeltaMovement().add(new Vec3(toVec.x, 0, toVec.z).scale(0.2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float getPropellerRot() {
|
||||
return this.propellerRot;
|
||||
}
|
||||
|
@ -427,14 +461,13 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
|
|||
hitEntityCrash(controller, target);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void hitEntityCrash(Player controller, Entity target) {
|
||||
if (lastTickSpeed > 0.12) {
|
||||
if (this.entityData.get(KAMIKAZE) && 20 * lastTickSpeed > this.getHealth()) {
|
||||
target.hurt(ModDamageTypes.causeCustomExplosionDamage(this.level().registryAccess(), this, controller), ExplosionConfig.DRONE_KAMIKAZE_HIT_DAMAGE.get());
|
||||
if (controller.getMainHandItem().is(ModItems.MONITOR.get())) {
|
||||
if (controller != null && controller.getMainHandItem().is(ModItems.MONITOR.get())) {
|
||||
Monitor.disLink(controller.getMainHandItem(), controller);
|
||||
}
|
||||
}
|
||||
|
@ -464,7 +497,6 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
|
|||
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
String id = this.entityData.get(CONTROLLER);
|
||||
UUID uuid;
|
||||
try {
|
||||
|
@ -539,4 +571,22 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
|
|||
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float ignoreExplosionHorizontalKnockBack() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float ignoreExplosionVerticalKnockBack() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemovedFromWorld() {
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
ChunkLoadTool.unloadAllChunks(serverLevel, this, this.loadedChunks);
|
||||
}
|
||||
super.onRemovedFromWorld();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.atsuishio.superbwarfare.config.server.ExplosionDestroyConfig;
|
|||
import com.atsuishio.superbwarfare.entity.AnimatedEntity;
|
||||
import com.atsuishio.superbwarfare.init.*;
|
||||
import com.atsuishio.superbwarfare.network.message.ClientIndicatorMessage;
|
||||
import com.atsuishio.superbwarfare.tools.ChunkLoadTool;
|
||||
import com.atsuishio.superbwarfare.tools.CustomExplosion;
|
||||
import com.atsuishio.superbwarfare.tools.ParticleTool;
|
||||
import com.atsuishio.superbwarfare.tools.ProjectileTool;
|
||||
|
@ -25,7 +26,6 @@ import net.minecraft.world.entity.EntityType;
|
|||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.projectile.ThrowableItemProjectile;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Explosion;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
@ -35,7 +35,6 @@ import net.minecraft.world.phys.BlockHitResult;
|
|||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.world.ForgeChunkManager;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import net.minecraftforge.network.PlayMessages;
|
||||
|
@ -56,7 +55,7 @@ public class CannonShellEntity extends ThrowableItemProjectile implements GeoEnt
|
|||
public static final EntityDataAccessor<String> ANIMATION = SynchedEntityData.defineId(CannonShellEntity.class, EntityDataSerializers.STRING);
|
||||
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
|
||||
|
||||
public String animationprocedure = "empty";
|
||||
public String animationProcedure = "empty";
|
||||
private float damage = 0;
|
||||
private float radius = 0;
|
||||
private float explosionDamage = 0;
|
||||
|
@ -272,21 +271,8 @@ public class CannonShellEntity extends ThrowableItemProjectile implements GeoEnt
|
|||
ParticleTool.sendParticle(serverLevel, ParticleTypes.SMOKE, this.xo, this.yo, this.zo,
|
||||
1, 0, 0, 0, 0.001, true);
|
||||
|
||||
var movement = this.getDeltaMovement();
|
||||
var currentX = this.chunkPosition().x;
|
||||
var currentZ = this.chunkPosition().z;
|
||||
var nextX = movement.x > 0 ? currentX + 1 : currentX - 1;
|
||||
var nextZ = movement.z > 0 ? currentZ + 1 : currentZ - 1;
|
||||
|
||||
ForgeChunkManager.forceChunk(serverLevel, ModUtils.MODID, this, currentX, currentZ, true, false);
|
||||
ForgeChunkManager.forceChunk(serverLevel, ModUtils.MODID, this, currentX, nextZ, true, false);
|
||||
ForgeChunkManager.forceChunk(serverLevel, ModUtils.MODID, this, nextX, currentZ, true, false);
|
||||
ForgeChunkManager.forceChunk(serverLevel, ModUtils.MODID, this, nextX, nextZ, true, false);
|
||||
|
||||
this.loadedChunks.add(ChunkPos.asLong(currentX, currentZ));
|
||||
this.loadedChunks.add(ChunkPos.asLong(currentX, nextZ));
|
||||
this.loadedChunks.add(ChunkPos.asLong(nextX, currentZ));
|
||||
this.loadedChunks.add(ChunkPos.asLong(nextX, nextZ));
|
||||
// 更新需要加载的区块
|
||||
ChunkLoadTool.updateLoadedChunks(serverLevel, this, this.loadedChunks);
|
||||
}
|
||||
if (this.tickCount > 600 || this.isInWater()) {
|
||||
if (this.level() instanceof ServerLevel) {
|
||||
|
@ -353,20 +339,20 @@ public class CannonShellEntity extends ThrowableItemProjectile implements GeoEnt
|
|||
}
|
||||
|
||||
private PlayState movementPredicate(AnimationState<CannonShellEntity> event) {
|
||||
if (this.animationprocedure.equals("empty")) {
|
||||
if (this.animationProcedure.equals("empty")) {
|
||||
return event.setAndContinue(RawAnimation.begin().thenLoop("animation.cannon_shell.idle"));
|
||||
}
|
||||
return PlayState.STOP;
|
||||
}
|
||||
|
||||
private PlayState procedurePredicate(AnimationState<CannonShellEntity> event) {
|
||||
if (!animationprocedure.equals("empty") && event.getController().getAnimationState() == AnimationController.State.STOPPED) {
|
||||
event.getController().setAnimation(RawAnimation.begin().thenPlay(this.animationprocedure));
|
||||
if (!animationProcedure.equals("empty") && event.getController().getAnimationState() == AnimationController.State.STOPPED) {
|
||||
event.getController().setAnimation(RawAnimation.begin().thenPlay(this.animationProcedure));
|
||||
if (event.getController().getAnimationState() == AnimationController.State.STOPPED) {
|
||||
this.animationprocedure = "empty";
|
||||
this.animationProcedure = "empty";
|
||||
event.getController().forceAnimationReset();
|
||||
}
|
||||
} else if (animationprocedure.equals("empty")) {
|
||||
} else if (animationProcedure.equals("empty")) {
|
||||
return PlayState.STOP;
|
||||
}
|
||||
return PlayState.CONTINUE;
|
||||
|
@ -387,7 +373,7 @@ public class CannonShellEntity extends ThrowableItemProjectile implements GeoEnt
|
|||
|
||||
@Override
|
||||
public void setAnimationProcedure(String procedure) {
|
||||
this.animationprocedure = procedure;
|
||||
this.animationProcedure = procedure;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -404,9 +390,7 @@ public class CannonShellEntity extends ThrowableItemProjectile implements GeoEnt
|
|||
@Override
|
||||
public void onRemovedFromWorld() {
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
for (long chunkPos : this.loadedChunks) {
|
||||
ForgeChunkManager.forceChunk(serverLevel, ModUtils.MODID, this, ChunkPos.getX(chunkPos), ChunkPos.getZ(chunkPos), false, false);
|
||||
}
|
||||
ChunkLoadTool.unloadAllChunks(serverLevel, this, this.loadedChunks);
|
||||
}
|
||||
super.onRemovedFromWorld();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package com.atsuishio.superbwarfare.entity.projectile;
|
||||
|
||||
import com.atsuishio.superbwarfare.init.ModEntities;
|
||||
import com.atsuishio.superbwarfare.tools.ProjectileTool;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.projectile.ThrowableItemProjectile;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
import net.minecraftforge.network.PlayMessages;
|
||||
|
||||
public class MelonBombEntity extends ThrowableItemProjectile {
|
||||
public MelonBombEntity(EntityType<? extends MelonBombEntity> type, Level world) {
|
||||
super(type, world);
|
||||
this.noCulling = true;
|
||||
}
|
||||
|
||||
public MelonBombEntity(LivingEntity entity, Level level) {
|
||||
super(ModEntities.MELON_BOMB.get(), entity, level);
|
||||
}
|
||||
|
||||
public MelonBombEntity(PlayMessages.SpawnEntity spawnEntity, Level level) {
|
||||
this(ModEntities.MELON_BOMB.get(), level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet<ClientGamePacketListener> getAddEntityPacket() {
|
||||
return NetworkHooks.getEntitySpawningPacket(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item getDefaultItem() {
|
||||
return Items.MELON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRenderAtSqrDistance(double pDistance) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHitBlock(BlockHitResult blockHitResult) {
|
||||
super.onHitBlock(blockHitResult);
|
||||
ProjectileTool.causeCustomExplode(this, 1000, 16, 1.5f);
|
||||
this.discard();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (tickCount > 600) {
|
||||
this.discard();
|
||||
if (!this.level().isClientSide) {
|
||||
ProjectileTool.causeCustomExplode(this, 1000, 16, 1.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// if (!this.level().isClientSide() && this.level() instanceof ServerLevel serverLevel) {
|
||||
// ParticleTool.sendParticle(serverLevel, ParticleTypes.SMOKE, this.xo, this.yo, this.zo,
|
||||
// 1, 0, 0, 0, 0.01, true);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getGravity() {
|
||||
return 0.05F;
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package com.atsuishio.superbwarfare.entity.projectile;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import com.atsuishio.superbwarfare.config.server.ExplosionConfig;
|
||||
import com.atsuishio.superbwarfare.init.ModDamageTypes;
|
||||
import com.atsuishio.superbwarfare.init.ModEntities;
|
||||
import com.atsuishio.superbwarfare.init.ModItems;
|
||||
import com.atsuishio.superbwarfare.tools.ChunkLoadTool;
|
||||
import com.atsuishio.superbwarfare.tools.ParticleTool;
|
||||
import com.atsuishio.superbwarfare.tools.ProjectileTool;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -25,7 +25,6 @@ import net.minecraft.world.level.block.BellBlock;
|
|||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraftforge.common.world.ForgeChunkManager;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
import net.minecraftforge.network.PlayMessages;
|
||||
import software.bernie.geckolib.animatable.GeoEntity;
|
||||
|
@ -158,21 +157,8 @@ public class MortarShellEntity extends ThrowableItemProjectile implements GeoEnt
|
|||
ParticleTool.sendParticle(serverLevel, ParticleTypes.CAMPFIRE_COSY_SMOKE, this.xo, this.yo, this.zo,
|
||||
1, 0, 0, 0, 0.001, true);
|
||||
|
||||
var movement = this.getDeltaMovement();
|
||||
var currentX = this.chunkPosition().x;
|
||||
var currentZ = this.chunkPosition().z;
|
||||
var nextX = movement.x > 0 ? currentX + 1 : currentX - 1;
|
||||
var nextZ = movement.z > 0 ? currentZ + 1 : currentZ - 1;
|
||||
|
||||
ForgeChunkManager.forceChunk(serverLevel, ModUtils.MODID, this, currentX, currentZ, true, false);
|
||||
ForgeChunkManager.forceChunk(serverLevel, ModUtils.MODID, this, currentX, nextZ, true, false);
|
||||
ForgeChunkManager.forceChunk(serverLevel, ModUtils.MODID, this, nextX, currentZ, true, false);
|
||||
ForgeChunkManager.forceChunk(serverLevel, ModUtils.MODID, this, nextX, nextZ, true, false);
|
||||
|
||||
this.loadedChunks.add(ChunkPos.asLong(currentX, currentZ));
|
||||
this.loadedChunks.add(ChunkPos.asLong(currentX, nextZ));
|
||||
this.loadedChunks.add(ChunkPos.asLong(nextX, currentZ));
|
||||
this.loadedChunks.add(ChunkPos.asLong(nextX, nextZ));
|
||||
// 更新需要加载的区块
|
||||
ChunkLoadTool.updateLoadedChunks(serverLevel, this, this.loadedChunks);
|
||||
}
|
||||
if (this.tickCount > this.life || this.isInWater()) {
|
||||
if (this.level() instanceof ServerLevel) {
|
||||
|
@ -199,9 +185,7 @@ public class MortarShellEntity extends ThrowableItemProjectile implements GeoEnt
|
|||
@Override
|
||||
public void onRemovedFromWorld() {
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
for (long chunkPos : this.loadedChunks) {
|
||||
ForgeChunkManager.forceChunk(serverLevel, ModUtils.MODID, this, ChunkPos.getX(chunkPos), ChunkPos.getZ(chunkPos), false, false);
|
||||
}
|
||||
ChunkLoadTool.unloadAllChunks(serverLevel, this, this.loadedChunks);
|
||||
}
|
||||
super.onRemovedFromWorld();
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ public class RpgRocketEntity extends ThrowableItemProjectile implements GeoEntit
|
|||
public static final EntityDataAccessor<String> ANIMATION = SynchedEntityData.defineId(RpgRocketEntity.class, EntityDataSerializers.STRING);
|
||||
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
|
||||
|
||||
public String animationprocedure = "empty";
|
||||
public String animationProcedure = "empty";
|
||||
|
||||
private float monsterMultiplier = 0.0f;
|
||||
private float damage = 250f;
|
||||
|
@ -205,7 +205,7 @@ public class RpgRocketEntity extends ThrowableItemProjectile implements GeoEntit
|
|||
|
||||
@Override
|
||||
public void setAnimationProcedure(String procedure) {
|
||||
this.animationprocedure = procedure;
|
||||
this.animationProcedure = procedure;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -154,6 +154,8 @@ public class Ah6Entity extends ContainerMobileEntity implements GeoEntity, IHeli
|
|||
propellerRotO = this.getPropellerRot();
|
||||
super.baseTick();
|
||||
|
||||
setZRot(getRoll() * 0.995f);
|
||||
|
||||
if (heat > 0) {
|
||||
heat--;
|
||||
}
|
||||
|
@ -275,14 +277,14 @@ public class Ah6Entity extends ContainerMobileEntity implements GeoEntity, IHeli
|
|||
}
|
||||
|
||||
this.setYRot(this.getYRot() + Mth.clamp((this.onGround() ? 0.1f : 2f) * diffY * this.entityData.get(PROPELLER_ROT) - 0.5f * this.entityData.get(DELTA_ROT), -8f, 8f));
|
||||
this.setXRot(Mth.clamp(this.getXRot() + (this.onGround() ? 0 : 1.4f) * diffX * this.entityData.get(PROPELLER_ROT), -80, 80));
|
||||
this.setZRot(Mth.clamp(this.getRoll() - this.entityData.get(DELTA_ROT) + (this.onGround() ? 0 : 0.2f) * diffY * this.entityData.get(PROPELLER_ROT), -80, 80));
|
||||
this.setXRot(Mth.clamp(this.getXRot() + ((this.onGround()) ? 0 : 1.4f) * diffX * this.entityData.get(PROPELLER_ROT), -80, 80));
|
||||
this.setZRot(this.getRoll() - this.entityData.get(DELTA_ROT) + (this.onGround() ? 0 : 0.2f) * diffY * this.entityData.get(PROPELLER_ROT));
|
||||
}
|
||||
|
||||
if (this.level() instanceof ServerLevel) {
|
||||
if (this.getEnergy() > 0) {
|
||||
boolean up = this.upInputDown || this.forwardInputDown;
|
||||
boolean down = this.downInputDown || this.backInputDown;
|
||||
boolean up = upInputDown || forwardInputDown;
|
||||
boolean down = this.downInputDown;
|
||||
|
||||
if (!engineStart && up) {
|
||||
engineStart = true;
|
||||
|
@ -293,19 +295,26 @@ public class Ah6Entity extends ContainerMobileEntity implements GeoEntity, IHeli
|
|||
this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + 0.002f, 0.12f));
|
||||
}
|
||||
|
||||
if (down && engineStartOver) {
|
||||
if (engineStartOver) {
|
||||
if (down) {
|
||||
this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - 0.0015f, this.onGround() ? 0 : 0.0375f));
|
||||
} else if (backInputDown) {
|
||||
this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - 0.0015f, this.onGround() ? 0 : 0.052f));
|
||||
if (passenger != null) {
|
||||
passenger.setXRot(0.8f * passenger.getXRot());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (engineStart && !engineStartOver) {
|
||||
this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + 0.0012f, 0.045f));
|
||||
}
|
||||
|
||||
if (!(up || down) && engineStartOver) {
|
||||
if (!(up || down || backInputDown) && engineStartOver) {
|
||||
if (this.getDeltaMovement().y() < 0) {
|
||||
this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + 0.0002f, 0.12f));
|
||||
this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + 0.0001f, 0.12f));
|
||||
} else {
|
||||
this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - (this.onGround() ? 0.00005f : 0.0002f), 0));
|
||||
this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - (this.onGround() ? 0.00005f : 0.0001f), 0));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -329,10 +338,10 @@ public class Ah6Entity extends ContainerMobileEntity implements GeoEntity, IHeli
|
|||
setDeltaMovement(getDeltaMovement().add(0.0f, Math.min(Math.sin((90 - this.getXRot()) * Mth.DEG_TO_RAD), Math.sin((90 + this.getRoll()) * Mth.DEG_TO_RAD)) * this.entityData.get(PROPELLER_ROT), 0.0f));
|
||||
|
||||
Vector3f direction = getRightDirection().mul(Math.cos((this.getRoll() + 90) * Mth.DEG_TO_RAD) * this.entityData.get(PROPELLER_ROT));
|
||||
setDeltaMovement(getDeltaMovement().add(new Vec3(direction.x, direction.y, direction.z).scale(0.85)));
|
||||
setDeltaMovement(getDeltaMovement().add(new Vec3(direction.x, direction.y, direction.z).scale(backInputDown ? 0.45 : 0.85)));
|
||||
|
||||
Vector3f directionZ = getForwardDirection().mul(-Math.cos((this.getXRot() + 90) * Mth.DEG_TO_RAD) * this.entityData.get(PROPELLER_ROT));
|
||||
setDeltaMovement(getDeltaMovement().add(new Vec3(directionZ.x, directionZ.y, directionZ.z).scale(0.35)));
|
||||
setDeltaMovement(getDeltaMovement().add(new Vec3(directionZ.x, directionZ.y, directionZ.z).scale(backInputDown ? 0.1 : 0.35)));
|
||||
|
||||
if (this.entityData.get(POWER) > 0.04f) {
|
||||
engineStartOver = true;
|
||||
|
@ -396,10 +405,6 @@ public class Ah6Entity extends ContainerMobileEntity implements GeoEntity, IHeli
|
|||
Vector4f worldPosition = transformPosition(transform, x, y, z);
|
||||
passenger.setPos(worldPosition.x, worldPosition.y, worldPosition.z);
|
||||
callback.accept(passenger, worldPosition.x, worldPosition.y, worldPosition.z);
|
||||
} else if (i == 1) {
|
||||
Vector4f worldPosition = transformPosition(transform, -x, y, z);
|
||||
passenger.setPos(worldPosition.x, worldPosition.y, worldPosition.z);
|
||||
callback.accept(passenger, worldPosition.x, worldPosition.y, worldPosition.z);
|
||||
}
|
||||
|
||||
if (passenger != this.getFirstPassenger()) {
|
||||
|
@ -412,7 +417,6 @@ public class Ah6Entity extends ContainerMobileEntity implements GeoEntity, IHeli
|
|||
public void copyEntityData(Entity entity) {
|
||||
float f = Mth.wrapDegrees(entity.getYRot() - getYRot());
|
||||
float g = Mth.clamp(f, -105.0f, 105.0f);
|
||||
|
||||
entity.yRotO += g - f;
|
||||
entity.setYRot(entity.getYRot() + g - f);
|
||||
entity.setYHeadRot(entity.getYRot());
|
||||
|
|
|
@ -257,11 +257,12 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
|
|||
this.setDeltaMovement(this.getDeltaMovement().add(0.0, fluidFloat, 0.0));
|
||||
|
||||
if (this.onGround()) {
|
||||
float f0 = 0.54f + 0.25f * Mth.abs(90 - (float) calculateAngle(this.getDeltaMovement(), this.getViewVector(1))) / 90 - 0.02f * Mth.abs(this.getRudderRot());
|
||||
float f0 = 0.54f + 0.25f * Mth.abs(90 - (float) calculateAngle(this.getDeltaMovement(), this.getViewVector(1))) / 90;
|
||||
this.setDeltaMovement(this.getDeltaMovement().add(this.getViewVector(1).normalize().scale(0.05 * this.getDeltaMovement().horizontalDistance())));
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply(f0, 0.85, f0));
|
||||
|
||||
} else if (this.isInWater()) {
|
||||
float f1 = 0.74f + 0.09f * Mth.abs(90 - (float) calculateAngle(this.getDeltaMovement(), this.getViewVector(1))) / 90 - 0.01f * Mth.abs(this.getRudderRot());
|
||||
float f1 = 0.74f + 0.09f * Mth.abs(90 - (float) calculateAngle(this.getDeltaMovement(), this.getViewVector(1))) / 90;
|
||||
this.setDeltaMovement(this.getDeltaMovement().add(this.getViewVector(1).normalize().scale(0.04 * this.getDeltaMovement().horizontalDistance())));
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply(f1, 0.85, f1));
|
||||
} else {
|
||||
|
@ -483,11 +484,11 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
|
|||
}
|
||||
|
||||
if (forwardInputDown) {
|
||||
this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + 0.015f, 0.2f));
|
||||
this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + (this.entityData.get(POWER) < 0 ? 0.012f : 0.0024f), 0.18f));
|
||||
}
|
||||
|
||||
if (backInputDown) {
|
||||
this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - 0.01f, -0.2f));
|
||||
this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - (this.entityData.get(POWER) > 0 ? 0.012f : 0.0024f), -0.13f));
|
||||
}
|
||||
|
||||
if (rightInputDown) {
|
||||
|
@ -500,7 +501,7 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
|
|||
this.extraEnergy(VehicleConfig.SPEEDBOAT_ENERGY_COST.get());
|
||||
}
|
||||
|
||||
this.entityData.set(POWER, this.entityData.get(POWER) * 0.97f);
|
||||
this.entityData.set(POWER, this.entityData.get(POWER) * (upInputDown ? 0.5f : (rightInputDown || leftInputDown) ? 0.977f : 0.99f));
|
||||
this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) * (float)Math.max(0.76f - 0.1f * this.getDeltaMovement().horizontalDistance(), 0.3));
|
||||
|
||||
float angle = (float) calculateAngle(this.getDeltaMovement(), this.getViewVector(1));
|
||||
|
@ -518,8 +519,8 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
|
|||
this.setRudderRot(Mth.clamp(this.getRudderRot() - this.entityData.get(DELTA_ROT), -0.8f, 0.8f) * 0.75f);
|
||||
|
||||
if (this.isInWater() || onGround()) {
|
||||
this.setYRot((float) (this.getYRot() - Math.max(12 * this.getDeltaMovement().horizontalDistance(), 0) * this.getRudderRot() * (this.entityData.get(POWER) > 0 ? 1 : -1)));
|
||||
this.setDeltaMovement(this.getDeltaMovement().add(Mth.sin(-this.getYRot() * 0.017453292F) * (isInWater() && !onGround() ? 0.3f : 1) * this.entityData.get(POWER), 0.0, Mth.cos(this.getYRot() * 0.017453292F) * (isInWater() && !onGround() ? 0.3f : 1) * this.entityData.get(POWER)));
|
||||
this.setYRot((float) (this.getYRot() - Math.max((isInWater() && !onGround() ? 5 : 10) * this.getDeltaMovement().horizontalDistance(), 0) * this.getRudderRot() * (this.entityData.get(POWER) > 0 ? 1 : -1)));
|
||||
this.setDeltaMovement(this.getDeltaMovement().add(Mth.sin(-this.getYRot() * 0.017453292F) * (!isInWater() && !onGround() ? 0.05f : (isInWater() && !onGround() ? 0.3f : 1)) * this.entityData.get(POWER), 0.0, Mth.cos(this.getYRot() * 0.017453292F) * (!isInWater() && !onGround() ? 0.05f : (isInWater() && !onGround() ? 0.3f : 1)) * this.entityData.get(POWER)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ public class MobileVehicleEntity extends EnergyVehicleEntity {
|
|||
collisionCoolDown--;
|
||||
}
|
||||
super.baseTick();
|
||||
preventStacking();
|
||||
crushEntities(this.getDeltaMovement());
|
||||
this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.06, 0.0));
|
||||
this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
|
@ -100,16 +101,17 @@ public class MobileVehicleEntity extends EnergyVehicleEntity {
|
|||
}
|
||||
collisionCoolDown = 4;
|
||||
crash = true;
|
||||
this.entityData.set(POWER, 0.4f * entityData.get(POWER));
|
||||
}
|
||||
}
|
||||
|
||||
public void bounceHorizontal(Direction direction) {
|
||||
switch (direction.getAxis()) {
|
||||
case X:
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply(-0.8, 0.99, 0.99));
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply(-0.4, 0.99, 0.99));
|
||||
break;
|
||||
case Z:
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply(0.99, 0.99, -0.8));
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply(0.99, 0.99, -0.4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -125,13 +127,36 @@ public class MobileVehicleEntity extends EnergyVehicleEntity {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 防止载具堆叠
|
||||
*/
|
||||
public void preventStacking() {
|
||||
var Box = getBoundingBox();
|
||||
|
||||
var entities = level().getEntities(EntityTypeTest.forClass(Entity.class), Box, entity -> entity != this && entity != getFirstPassenger() && entity.getVehicle() == null)
|
||||
.stream().filter(entity -> entity instanceof VehicleEntity)
|
||||
.toList();
|
||||
|
||||
for (var entity : entities) {
|
||||
Vec3 toVec = this.position().add(new Vec3(1, 1 ,1).scale(random.nextFloat() * 0.01f + 1f)).vectorTo(entity.position());
|
||||
Vec3 velAdd = toVec.normalize().scale(Math.max((this.getBbWidth() + 2) - position().distanceTo(entity.position()), 0) * 0.002);
|
||||
double entitySize = entity.getBbWidth() * entity.getBbHeight();
|
||||
double thisSize = this.getBbWidth() * this.getBbHeight();
|
||||
double f = Math.min(entitySize / thisSize, 2);
|
||||
double f1 = Math.min(thisSize / entitySize, 2);
|
||||
|
||||
this.push(-f * velAdd.x, -f * velAdd.y, -f * velAdd.z);
|
||||
entity.push(f1 * velAdd.x, f1 * velAdd.y, f1 * velAdd.z);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 撞击实体并造成伤害
|
||||
* @param velocity 动量
|
||||
*/
|
||||
public void crushEntities(Vec3 velocity) {
|
||||
if (this instanceof DroneEntity) return;
|
||||
if (velocity.horizontalDistance() < 0.1) return;
|
||||
if (velocity.horizontalDistance() < 0.25) return;
|
||||
if (isRemoved()) return;
|
||||
var frontBox = getBoundingBox().move(velocity.scale(0.5));
|
||||
var velAdd = velocity.add(0, 0, 0).scale(0.9);
|
||||
|
@ -149,7 +174,7 @@ public class MobileVehicleEntity extends EnergyVehicleEntity {
|
|||
double f = Math.min(entitySize / thisSize, 2);
|
||||
double f1 = Math.min(thisSize / entitySize, 4);
|
||||
|
||||
if (velocity.length() > 0.3) {
|
||||
if (velocity.length() > 0.3 && getBoundingBox().distanceToSqr(entity.getBoundingBox().getCenter()) < 1) {
|
||||
if (!this.level().isClientSide) {
|
||||
this.level().playSound(null, this, ModSounds.VEHICLE_STRIKE.get(), this.getSoundSource(), 1, 1);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,363 @@
|
|||
package com.atsuishio.superbwarfare.entity.vehicle;
|
||||
|
||||
import com.atsuishio.superbwarfare.config.server.ExplosionDestroyConfig;
|
||||
import com.atsuishio.superbwarfare.entity.projectile.MelonBombEntity;
|
||||
import com.atsuishio.superbwarfare.init.ModDamageTypes;
|
||||
import com.atsuishio.superbwarfare.init.ModEntities;
|
||||
import com.atsuishio.superbwarfare.init.ModSounds;
|
||||
import com.atsuishio.superbwarfare.tools.CustomExplosion;
|
||||
import com.atsuishio.superbwarfare.tools.EntityFindUtil;
|
||||
import com.atsuishio.superbwarfare.tools.ParticleTool;
|
||||
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.sounds.SoundEvent;
|
||||
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.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Explosion;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.event.ForgeEventFactory;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
import net.minecraftforge.network.PlayMessages;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.joml.Math;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector4f;
|
||||
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.util.GeckoLibUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Tom6Entity extends MobileVehicleEntity implements GeoEntity {
|
||||
public static final EntityDataAccessor<Float> DELTA_ROT = SynchedEntityData.defineId(Tom6Entity.class, EntityDataSerializers.FLOAT);
|
||||
public static final EntityDataAccessor<Boolean> MELON = SynchedEntityData.defineId(Tom6Entity.class, EntityDataSerializers.BOOLEAN);
|
||||
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
|
||||
public static final float MAX_HEALTH = 50;
|
||||
public static final int MAX_ENERGY = 100000;
|
||||
|
||||
public Tom6Entity(PlayMessages.SpawnEntity packet, Level world) {
|
||||
this(ModEntities.TOM_6.get(), world);
|
||||
}
|
||||
|
||||
public Tom6Entity(EntityType<Tom6Entity> type, Level world) {
|
||||
super(type, world);
|
||||
this.setMaxUpStep(0.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData() {
|
||||
super.defineSynchedData();
|
||||
this.entityData.define(DELTA_ROT, 0f);
|
||||
this.entityData.define(MELON, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag compound) {
|
||||
super.addAdditionalSaveData(compound);
|
||||
compound.putBoolean("Melon", this.entityData.get(MELON));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag compound) {
|
||||
super.readAdditionalSaveData(compound);
|
||||
this.entityData.set(MELON, compound.getBoolean("Melon"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet<ClientGamePacketListener> getAddEntityPacket() {
|
||||
return NetworkHooks.getEntitySpawningPacket(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hurt(DamageSource source, float amount) {
|
||||
super.hurt(source, amount);
|
||||
if (source.is(ModDamageTypes.VEHICLE_STRIKE)) {
|
||||
amount *= 2f;
|
||||
}
|
||||
this.level().playSound(null, this.getOnPos(), ModSounds.HIT.get(), SoundSource.PLAYERS, 1, 1);
|
||||
this.hurt(amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult interact(Player player, InteractionHand hand) {
|
||||
if (player.getMainHandItem().is(Items.MELON) && !entityData.get(MELON)) {
|
||||
entityData.set(MELON, true);
|
||||
player.getMainHandItem().shrink(1);
|
||||
player.level().playSound(player, this.getOnPos(), SoundEvents.WOOD_PLACE, SoundSource.PLAYERS, 1, 1);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
return super.interact(player, hand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void baseTick() {
|
||||
super.baseTick();
|
||||
float f;
|
||||
|
||||
f = (float) Mth.clamp(0.759f + 0.041f * Mth.abs(90 - (float) calculateAngle(this.getDeltaMovement(), this.getViewVector(1))) / 90, 0.01, 0.99);
|
||||
|
||||
this.setDeltaMovement(this.getDeltaMovement().add(this.getViewVector(1).scale((0.24) * this.getDeltaMovement().length())));
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply(f, f, f));
|
||||
this.refreshDimensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void travel() {
|
||||
Entity passenger = this.getPassengers().isEmpty() ? null : this.getPassengers().get(0);
|
||||
|
||||
// if (this.getEnergy() <= 0) return;
|
||||
|
||||
float diffX;
|
||||
float diffY;
|
||||
|
||||
if (passenger == null) {
|
||||
this.leftInputDown = false;
|
||||
this.rightInputDown = false;
|
||||
this.forwardInputDown = false;
|
||||
this.backInputDown = false;
|
||||
this.setZRot(this.roll * 0.8f);
|
||||
this.setXRot(this.getXRot() * 0.7f);
|
||||
this.entityData.set(POWER, this.entityData.get(POWER) * 0.98f);
|
||||
if (onGround()) {
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply(0.8, 1, 0.8));
|
||||
}
|
||||
} else if (passenger instanceof Player player) {
|
||||
|
||||
// SoundTool.playLocalSound(player, SoundEvents.ELYTRA_FLYING);
|
||||
|
||||
diffY = Math.clamp(-90f, 90f, Mth.wrapDegrees(passenger.getYHeadRot() - this.getYRot()));
|
||||
diffX = Math.clamp(-60f, 60f, Mth.wrapDegrees(passenger.getXRot() - this.getXRot()));
|
||||
|
||||
if (!onGround()) {
|
||||
if (rightInputDown) {
|
||||
this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) - 0.4f);
|
||||
} else if (this.leftInputDown) {
|
||||
this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) + 0.4f);
|
||||
}
|
||||
}
|
||||
|
||||
float roll = Mth.abs(Mth.clamp(getRoll() / 60 , -1.5f , 1.5f));
|
||||
|
||||
float addY = Mth.clamp(Math.min((this.onGround() ? 1.5f : 0.9f) * (float) Math.max(getDeltaMovement().length() - 0.06, 0.1), 0.9f) * diffY - 0.5f * this.entityData.get(DELTA_ROT), (entityData.get(MELON) ? -2f : -3f) * (roll + 1), (entityData.get(MELON) ? 2f : 3f) * (roll + 1));
|
||||
float addX = Mth.clamp(Math.min((float) Math.max(getDeltaMovement().length() - 0.1, 0.01), 0.9f) * diffX, (entityData.get(MELON) ? -3f : -4f), (entityData.get(MELON) ? 3f : 4f));
|
||||
|
||||
this.setYRot(this.getYRot() + addY);
|
||||
this.setXRot(Mth.clamp(this.getXRot() + addX, onGround() ? -10 : -120, onGround() ? 2 : 120));
|
||||
this.setZRot(this.getRoll() - this.entityData.get(DELTA_ROT) + (this.onGround() ? 0 : 0.01f) * diffY * (float) getDeltaMovement().length());
|
||||
|
||||
if (upInputDown && !onGround() && entityData.get(MELON)) {
|
||||
entityData.set(MELON, false);
|
||||
|
||||
Matrix4f transform = getVehicleTransform();
|
||||
Vector4f worldPosition;
|
||||
worldPosition = transformPosition(transform, 0, -0.2f, 0);
|
||||
|
||||
MelonBombEntity melonBomb = new MelonBombEntity(player, player.level());
|
||||
melonBomb.setPos(worldPosition.x, worldPosition.y, worldPosition.z);
|
||||
melonBomb.shoot(this.getDeltaMovement().x, this.getDeltaMovement().y, this.getDeltaMovement().z, 0.96f * (float)this.getDeltaMovement().length(), 0);
|
||||
passenger.level().addFreshEntity(melonBomb);
|
||||
|
||||
this.level().playSound(null, this.getOnPos(), SoundEvents.IRON_DOOR_OPEN, SoundSource.PLAYERS, 1, 1);
|
||||
upInputDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (forwardInputDown) {
|
||||
this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + (entityData.get(MELON) ? 0.003f : 0.0022f), entityData.get(MELON) ? 0.12f : 0.15f));
|
||||
}
|
||||
|
||||
if (backInputDown || downInputDown) {
|
||||
this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - 0.006f, onGround() ? -0.12f : 0.04f));
|
||||
}
|
||||
|
||||
if (onGround()) {
|
||||
setXRot(getXRot() * 0.7f);
|
||||
setZRot(getRoll() * 0.7f);
|
||||
} else {
|
||||
setZRot(getRoll() * 0.994f);
|
||||
}
|
||||
|
||||
// if (this.forwardInputDown || this.backInputDown) {
|
||||
// this.extraEnergy(VehicleConfig.SPEEDBOAT_ENERGY_COST.get());
|
||||
// }
|
||||
|
||||
this.entityData.set(POWER, this.entityData.get(POWER) * 0.99f);
|
||||
this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) * 0.95f);
|
||||
|
||||
this.setDeltaMovement(this.getDeltaMovement().add(
|
||||
Mth.sin(-this.getYRot() * 0.017453292F) * (entityData.get(MELON) ? 0.16f : 0.19f) * this.entityData.get(POWER),
|
||||
Mth.clamp(Math.sin((onGround() ? 45 : -(getXRot() - 30)) * Mth.DEG_TO_RAD) * getDeltaMovement().horizontalDistance() * (entityData.get(MELON) ? 0.047f : 0.067f), -0.04, 0.09),
|
||||
Mth.cos(this.getYRot() * 0.017453292F) * (entityData.get(MELON) ? 0.16f : 0.19f) * this.entityData.get(POWER)
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoundEvent getEngineSound() {
|
||||
return ModSounds.WHEEL_CHAIR_ENGINE.get();
|
||||
}
|
||||
|
||||
protected void clampRotation(Entity entity) {
|
||||
float f = Mth.wrapDegrees(entity.getXRot() - this.getXRot());
|
||||
float f1 = Mth.clamp(f, -85.0F, 60F);
|
||||
entity.xRotO += f1 - f;
|
||||
entity.setXRot(entity.getXRot() + f1 - f);
|
||||
|
||||
entity.setYBodyRot(this.getYRot());
|
||||
float f2 = Mth.wrapDegrees(entity.getYRot() - this.getYRot());
|
||||
float f3 = Mth.clamp(f2, -45.0F, 45.0F);
|
||||
entity.yRotO += f3 - f2;
|
||||
entity.setYRot(entity.getYRot() + f3 - f2);
|
||||
entity.setYBodyRot(this.getYRot());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPassengerTurned(Entity entity) {
|
||||
this.clampRotation(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void positionRider(@NotNull Entity passenger, @NotNull MoveFunction callback) {
|
||||
// From Immersive_Aircraft
|
||||
if (!this.hasPassenger(passenger)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Matrix4f transform = getVehicleTransform();
|
||||
|
||||
float x = 0f;
|
||||
float y = 0.95f;
|
||||
float z = -0.4f;
|
||||
y += (float) passenger.getMyRidingOffset();
|
||||
|
||||
int i = this.getPassengers().indexOf(passenger);
|
||||
|
||||
if (i == 0) {
|
||||
Vector4f worldPosition = transformPosition(transform, x, y, z);
|
||||
passenger.setPos(worldPosition.x, worldPosition.y, worldPosition.z);
|
||||
callback.accept(passenger, worldPosition.x, worldPosition.y, worldPosition.z);
|
||||
}
|
||||
|
||||
if (passenger != this.getFirstPassenger()) {
|
||||
passenger.setXRot(passenger.getXRot() + (getXRot() - xRotO));
|
||||
}
|
||||
|
||||
copyEntityData(passenger);
|
||||
}
|
||||
|
||||
public void copyEntityData(Entity entity) {
|
||||
float f = Mth.wrapDegrees(entity.getYRot() - getYRot());
|
||||
float g = Mth.clamp(f, -105.0f, 105.0f);
|
||||
entity.yRotO += g - f;
|
||||
entity.setYRot(entity.getYRot() + g - f);
|
||||
entity.setYHeadRot(entity.getYRot());
|
||||
entity.setYBodyRot(getYRot());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
Entity attacker = EntityFindUtil.findEntity(this.level(), this.entityData.get(LAST_ATTACKER_UUID));
|
||||
if (this.crash) {
|
||||
List<Entity> passengers = this.getPassengers();
|
||||
for (var entity : passengers) {
|
||||
if (entity instanceof LivingEntity living) {
|
||||
var tempAttacker = living == attacker ? null : attacker;
|
||||
|
||||
living.hurt(ModDamageTypes.causeAirCrashDamage(this.level().registryAccess(), null, tempAttacker), Integer.MAX_VALUE);
|
||||
living.invulnerableTime = 0;
|
||||
living.hurt(ModDamageTypes.causeAirCrashDamage(this.level().registryAccess(), null, tempAttacker), Integer.MAX_VALUE);
|
||||
living.invulnerableTime = 0;
|
||||
living.hurt(ModDamageTypes.causeAirCrashDamage(this.level().registryAccess(), null, tempAttacker), Integer.MAX_VALUE);
|
||||
living.invulnerableTime = 0;
|
||||
living.hurt(ModDamageTypes.causeAirCrashDamage(this.level().registryAccess(), null, tempAttacker), Integer.MAX_VALUE);
|
||||
living.invulnerableTime = 0;
|
||||
living.hurt(ModDamageTypes.causeAirCrashDamage(this.level().registryAccess(), null, tempAttacker), Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<Entity> passengers = this.getPassengers();
|
||||
for (var entity : passengers) {
|
||||
if (entity instanceof LivingEntity living) {
|
||||
var tempAttacker = living == attacker ? null : attacker;
|
||||
|
||||
living.hurt(ModDamageTypes.causeVehicleExplosionDamage(this.level().registryAccess(), null, tempAttacker), Integer.MAX_VALUE);
|
||||
living.invulnerableTime = 0;
|
||||
living.hurt(ModDamageTypes.causeVehicleExplosionDamage(this.level().registryAccess(), null, tempAttacker), Integer.MAX_VALUE);
|
||||
living.invulnerableTime = 0;
|
||||
living.hurt(ModDamageTypes.causeVehicleExplosionDamage(this.level().registryAccess(), null, tempAttacker), Integer.MAX_VALUE);
|
||||
living.invulnerableTime = 0;
|
||||
living.hurt(ModDamageTypes.causeVehicleExplosionDamage(this.level().registryAccess(), null, tempAttacker), Integer.MAX_VALUE);
|
||||
living.invulnerableTime = 0;
|
||||
living.hurt(ModDamageTypes.causeVehicleExplosionDamage(this.level().registryAccess(), null, tempAttacker), Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (level() instanceof ServerLevel) {
|
||||
if (entityData.get(MELON)) {
|
||||
CustomExplosion explosion = new CustomExplosion(this.level(), this,
|
||||
ModDamageTypes.causeCustomExplosionDamage(this.level().registryAccess(), this, attacker), 1100.0f,
|
||||
this.getX(), this.getY(), this.getZ(), 16f, ExplosionDestroyConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP).setDamageMultiplier(1);
|
||||
explosion.explode();
|
||||
ForgeEventFactory.onExplosionStart(this.level(), explosion);
|
||||
explosion.finalizeExplosion(false);
|
||||
ParticleTool.spawnHugeExplosionParticles(this.level(), this.position());
|
||||
} else {
|
||||
CustomExplosion explosion = new CustomExplosion(this.level(), this,
|
||||
ModDamageTypes.causeCustomExplosionDamage(this.level().registryAccess(), this, attacker), 15.0f,
|
||||
this.getX(), this.getY(), this.getZ(), 2f, ExplosionDestroyConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP).setDamageMultiplier(1);
|
||||
explosion.explode();
|
||||
ForgeEventFactory.onExplosionStart(this.level(), explosion);
|
||||
explosion.finalizeExplosion(false);
|
||||
ParticleTool.spawnMediumExplosionParticles(this.level(), this.position());
|
||||
}
|
||||
}
|
||||
|
||||
this.discard();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float ignoreExplosionHorizontalKnockBack() {
|
||||
return -0.2f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float ignoreExplosionVerticalKnockBack() {
|
||||
return -0.3f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerControllers(AnimatableManager.ControllerRegistrar data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxHealth() {
|
||||
return MAX_HEALTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergy() {
|
||||
return MAX_ENERGY;
|
||||
}
|
||||
}
|
|
@ -239,7 +239,6 @@ public class VehicleEntity extends Entity {
|
|||
lastHurtTick ++;
|
||||
|
||||
prevRoll = this.getRoll();
|
||||
setZRot(roll * 0.9f);
|
||||
|
||||
float delta = Math.abs(getYRot() - yRotO);
|
||||
while (getYRot() > 180F) {
|
||||
|
|
|
@ -78,6 +78,10 @@ public class ModEntities {
|
|||
EntityType.Builder.<FlareDecoyEntity>of(FlareDecoyEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(FlareDecoyEntity::new).sized(0.5f, 0.5f));
|
||||
public static final RegistryObject<EntityType<Lav150Entity>> LAV_150 = register("lav_150",
|
||||
EntityType.Builder.<Lav150Entity>of(Lav150Entity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(Lav150Entity::new).fireImmune().sized(2.8f, 3.1f));
|
||||
public static final RegistryObject<EntityType<Tom6Entity>> TOM_6 = register("tom_6",
|
||||
EntityType.Builder.<Tom6Entity>of(Tom6Entity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(Tom6Entity::new).fireImmune().sized(1.05f, 1.0f));
|
||||
public static final RegistryObject<EntityType<MelonBombEntity>> MELON_BOMB = register("melon_bomb",
|
||||
EntityType.Builder.<MelonBombEntity>of(MelonBombEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(MelonBombEntity::new).sized(1f, 1f));
|
||||
|
||||
private static <T extends Entity> RegistryObject<EntityType<T>> register(String name, EntityType.Builder<T> entityTypeBuilder) {
|
||||
return REGISTRY.register(name, () -> entityTypeBuilder.build(name));
|
||||
|
|
|
@ -37,5 +37,7 @@ public class ModEntityRenderers {
|
|||
event.registerEntityRenderer(ModEntities.FLARE_DECOY.get(), FlareDecoyEntityRenderer::new);
|
||||
event.registerEntityRenderer(ModEntities.LAV_150.get(), Lav150Renderer::new);
|
||||
event.registerEntityRenderer(ModEntities.SMALL_CANNON_SHELL.get(), SmallCannonShellRenderer::new);
|
||||
event.registerEntityRenderer(ModEntities.TOM_6.get(), Tom6Renderer::new);
|
||||
event.registerEntityRenderer(ModEntities.MELON_BOMB.get(), MelonBombEntityRenderer::new);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,7 @@ public class ModTabs {
|
|||
output.accept(ContainerBlockItem.createInstance(ModEntities.WHEEL_CHAIR.get()));
|
||||
output.accept(ContainerBlockItem.createInstance(ModEntities.AH_6.get()));
|
||||
output.accept(ContainerBlockItem.createInstance(ModEntities.LAV_150.get()));
|
||||
output.accept(ContainerBlockItem.createInstance(ModEntities.TOM_6.get()));
|
||||
} else {
|
||||
output.accept(registryObject.get());
|
||||
if (registryObject.get() == ModItems.ARMOR_PLATE.get()) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import net.minecraft.world.item.Item;
|
|||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
|
@ -104,6 +105,12 @@ public class Monitor extends Item {
|
|||
return super.getAttributeModifiers(slot, stack);
|
||||
}
|
||||
|
||||
public static void getDronePos(ItemStack itemstack, Vec3 vec3) {
|
||||
itemstack.getOrCreateTag().putDouble("PosX", vec3.x);
|
||||
itemstack.getOrCreateTag().putDouble("PosY", vec3.y);
|
||||
itemstack.getOrCreateTag().putDouble("PosZ", vec3.z);
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, Level world, List<Component> list, TooltipFlag flag) {
|
||||
|
@ -112,11 +119,18 @@ public class Monitor extends Item {
|
|||
Player player = Minecraft.getInstance().player;
|
||||
if (player == null) return;
|
||||
|
||||
DroneEntity drone = EntityFindUtil.findDrone(player.level(), stack.getOrCreateTag().getString(LINKED_DRONE));
|
||||
if (drone == null) return;
|
||||
Vec3 droneVec = new Vec3(stack.getOrCreateTag().getDouble("PosX"), stack.getOrCreateTag().getDouble("PosY"), stack.getOrCreateTag().getDouble("PosZ"));
|
||||
|
||||
list.add(Component.translatable("des.superbwarfare.monitor",
|
||||
new DecimalFormat("##.#").format(player.distanceTo(drone)) + "m").withStyle(ChatFormatting.GRAY));
|
||||
list.add(Component.translatable("des.superbwarfare.monitor",new DecimalFormat("##.#").format(player.position().distanceTo(droneVec)) + "m").withStyle(ChatFormatting.GRAY));
|
||||
list.add(Component.literal("X: " + new DecimalFormat("##.#").format(droneVec.x) +
|
||||
" Y: " + new DecimalFormat("##.#").format(droneVec.y) +
|
||||
" Z: " + new DecimalFormat("##.#").format(droneVec.z)
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -294,7 +294,7 @@ public class ReforgingTableMenu extends AbstractContainerMenu {
|
|||
ItemStack output = gun.copy();
|
||||
PerkHelper.removePerkByType(output, perkItem.getPerk().type);
|
||||
GunsTool.setGunDoubleTag(output, "UpgradePoint", Math.min(MAX_UPGRADE_POINT, level - 1 + GunsTool.getGunDoubleTag(output, "UpgradePoint", 0)));
|
||||
this.upgradePoint.set((int) GunsTool.getGunDoubleTag(gun, "UpgradePoint", 0));
|
||||
this.upgradePoint.set((int) GunsTool.getGunDoubleTag(output, "UpgradePoint", 0));
|
||||
|
||||
this.container.setItem(INPUT_SLOT, output);
|
||||
this.container.setChanged();
|
||||
|
|
|
@ -128,6 +128,11 @@ public abstract class CameraMixin {
|
|||
return;
|
||||
}
|
||||
|
||||
if (thirdPerson && entity.getVehicle() instanceof Tom6Entity) {
|
||||
move(-getMaxZoom(4), 1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thirdPerson && entity.getVehicle() instanceof Lav150Entity && !ClientEventHandler.zoomVehicle) {
|
||||
move(-getMaxZoom(2.75), 1, 0.0);
|
||||
return;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.atsuishio.superbwarfare.mixins;
|
||||
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.Ah6Entity;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.Tom6Entity;
|
||||
import com.atsuishio.superbwarfare.init.ModTags;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Axis;
|
||||
|
@ -69,5 +70,30 @@ public class GameRendererMixin {
|
|||
matrices.mulPose(Axis.YP.rotationDegrees(-mainCamera.getYRot() - 180.0f));
|
||||
matrices.mulPose(Axis.XP.rotationDegrees(-mainCamera.getXRot()));
|
||||
}
|
||||
|
||||
if (entity != null && !mainCamera.isDetached() && entity.getRootVehicle() instanceof Tom6Entity vehicle) {
|
||||
// rotate camera
|
||||
|
||||
matrices.mulPose(Axis.ZP.rotationDegrees(vehicle.getRoll(tickDelta)));
|
||||
// matrices.mulPose(Axis.XP.rotationDegrees(vehicle.getViewXRot(tickDelta)));
|
||||
|
||||
// fetch eye offset
|
||||
float eye = entity.getEyeHeight();
|
||||
|
||||
// transform eye offset to match aircraft rotation
|
||||
Vector3f offset = new Vector3f(0, -eye, 0);
|
||||
Quaternionf quaternion = Axis.XP.rotationDegrees(0.0f);
|
||||
quaternion.mul(Axis.YP.rotationDegrees(-vehicle.getViewYRot(tickDelta)));
|
||||
quaternion.mul(Axis.XP.rotationDegrees(vehicle.getViewXRot(tickDelta)));
|
||||
quaternion.mul(Axis.ZP.rotationDegrees(vehicle.getRoll(tickDelta)));
|
||||
offset.rotate(quaternion);
|
||||
|
||||
// apply camera offset
|
||||
matrices.mulPose(Axis.XP.rotationDegrees(mainCamera.getXRot()));
|
||||
matrices.mulPose(Axis.YP.rotationDegrees(mainCamera.getYRot() + 180.0f));
|
||||
matrices.translate(offset.x(), offset.y() + eye, offset.z());
|
||||
matrices.mulPose(Axis.YP.rotationDegrees(-mainCamera.getYRot() - 180.0f));
|
||||
matrices.mulPose(Axis.XP.rotationDegrees(-mainCamera.getXRot()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.atsuishio.superbwarfare.mixins;
|
||||
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.Ah6Entity;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.Tom6Entity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Axis;
|
||||
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
|
||||
|
@ -19,5 +20,9 @@ public class LivingEntityRendererMixin<T extends LivingEntity> {
|
|||
matrices.mulPose(Axis.XP.rotationDegrees(-ah6Entity.getViewXRot(tickDelta)));
|
||||
matrices.mulPose(Axis.ZP.rotationDegrees(-ah6Entity.getRoll(tickDelta)));
|
||||
}
|
||||
if (entity.getRootVehicle() != entity && entity.getRootVehicle() instanceof Tom6Entity tom6Entity) {
|
||||
matrices.mulPose(Axis.XP.rotationDegrees(-tom6Entity.getViewXRot(tickDelta)));
|
||||
matrices.mulPose(Axis.ZP.rotationDegrees(-tom6Entity.getRoll(tickDelta)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.atsuishio.superbwarfare.config.client.VehicleControlConfig;
|
|||
import com.atsuishio.superbwarfare.entity.vehicle.Ah6Entity;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.ICannonEntity;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.Lav150Entity;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.Tom6Entity;
|
||||
import com.atsuishio.superbwarfare.event.ClientEventHandler;
|
||||
import com.atsuishio.superbwarfare.init.ModItems;
|
||||
import com.atsuishio.superbwarfare.init.ModMobEffects;
|
||||
|
@ -12,6 +13,7 @@ import com.atsuishio.superbwarfare.tools.GunsTool;
|
|||
import net.minecraft.client.CameraType;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
@ -78,7 +80,11 @@ public class MouseHandlerMixin {
|
|||
if (player == null) return i;
|
||||
|
||||
if (player.getVehicle() instanceof Ah6Entity ah6Entity && ah6Entity.getFirstPassenger() == player) {
|
||||
return VehicleControlConfig.INVERT_AIRCRAFT_CONTROL.get() ? -i : i;
|
||||
return VehicleControlConfig.INVERT_AIRCRAFT_CONTROL.get() ? (Mth.abs(ah6Entity.getRoll()) < 90 ? -i : i) : (Mth.abs(ah6Entity.getRoll()) < 90 ? i : -i);
|
||||
}
|
||||
|
||||
if (player.getVehicle() instanceof Tom6Entity tom6 && tom6.getFirstPassenger() == player) {
|
||||
return VehicleControlConfig.INVERT_AIRCRAFT_CONTROL.get() ? (Mth.abs(tom6.getRoll()) < 90 ? -i : i) : (Mth.abs(tom6.getRoll()) < 90 ? i : -i);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package com.atsuishio.superbwarfare.tools;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraftforge.common.world.ForgeChunkManager;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class ChunkLoadTool {
|
||||
|
||||
/**
|
||||
* 根据动量计算需要加载的区块并卸载不再需要加载的区块
|
||||
*/
|
||||
public static void updateLoadedChunks(ServerLevel level, Entity entity, Set<Long> loadedChunks) {
|
||||
var x = entity.position().x;
|
||||
var z = entity.position().z;
|
||||
var nextX = x + entity.getDeltaMovement().x;
|
||||
var nextZ = z + entity.getDeltaMovement().z;
|
||||
|
||||
// 加载当前区块和下一tick会进入的区块
|
||||
var newChunks = new HashSet<Long>();
|
||||
newChunks.add(ChunkPos.asLong(new BlockPos((int) x, 0, (int) z)));
|
||||
newChunks.add(ChunkPos.asLong(new BlockPos((int) nextX, 0, (int) nextZ)));
|
||||
|
||||
// 计算需要更新的区块
|
||||
var chunksToLoad = newChunks.stream().filter(chunk -> !loadedChunks.contains(chunk)).toList();
|
||||
var chunksToUnload = loadedChunks.stream().filter(chunk -> !newChunks.contains(chunk)).toList();
|
||||
|
||||
chunksToLoad.forEach(chunk -> {
|
||||
var chunkPos = new ChunkPos(chunk);
|
||||
ForgeChunkManager.forceChunk(level, ModUtils.MODID, entity, chunkPos.x, chunkPos.z, true, false);
|
||||
});
|
||||
|
||||
chunksToUnload.forEach(chunk -> {
|
||||
var chunkPos = new ChunkPos(chunk);
|
||||
ForgeChunkManager.forceChunk(level, ModUtils.MODID, entity, chunkPos.x, chunkPos.z, false, false);
|
||||
});
|
||||
|
||||
loadedChunks.clear();
|
||||
loadedChunks.addAll(newChunks);
|
||||
}
|
||||
|
||||
/**
|
||||
* 卸载所有已加载区块
|
||||
*/
|
||||
public static void unloadAllChunks(ServerLevel level, Entity entity, Set<Long> loadedChunks) {
|
||||
loadedChunks.forEach(chunk -> {
|
||||
var chunkPos = new ChunkPos(chunk);
|
||||
ForgeChunkManager.forceChunk(level, ModUtils.MODID, entity, chunkPos.x, chunkPos.z, false, false);
|
||||
});
|
||||
}
|
||||
}
|
1011
src/main/resources/assets/superbwarfare/geo/tom_6.geo.json
Normal file
1011
src/main/resources/assets/superbwarfare/geo/tom_6.geo.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -401,6 +401,8 @@
|
|||
"entity.superbwarfare.ah_6": "AH-6 Little Bird",
|
||||
"entity.superbwarfare.lav_150": "LAV-150 Commando",
|
||||
"entity.minecraft.villager.superbwarfare.armory": "Armory",
|
||||
"entity.superbwarfare.tom_6": "Tom F6F",
|
||||
"entity.superbwarfare.melon_bomb": "Melon Bomb",
|
||||
|
||||
"key.categories.superbwarfare": "Superb Warfare",
|
||||
"key.superbwarfare.hold_zoom": "Zoom(Hold)",
|
||||
|
|
|
@ -399,6 +399,8 @@
|
|||
"entity.superbwarfare.ah_6": "AH-6 小鸟直升机",
|
||||
"entity.superbwarfare.lav_150": "LAV-150 Commando",
|
||||
"entity.minecraft.villager.superbwarfare.armory": "军械师",
|
||||
"entity.superbwarfare.tom_6": "汤姆 F6F",
|
||||
"entity.superbwarfare.melon_bomb": "西瓜航弹",
|
||||
|
||||
"key.categories.superbwarfare": "卓越前线",
|
||||
"key.superbwarfare.hold_zoom": "瞄准(按住)",
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
Loading…
Add table
Reference in a new issue