Merge branch 'refs/heads/superbwarfare' into superbwarfare_c4

# Conflicts:
#	src/main/java/com/atsuishio/superbwarfare/entity/DroneEntity.java
This commit is contained in:
Light_Quanta 2025-01-22 22:48:43 +08:00
commit 87b82ca209
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
29 changed files with 1836 additions and 94 deletions

View file

@ -13,5 +13,5 @@ mod_description=A Warfare Mod
minecraft_version=1.20.1 minecraft_version=1.20.1
jei_version=15.2.0.27 jei_version=15.2.0.27
cloth_config_version=11.1.106 cloth_config_version=11.1.106
mod_version=0.4.0 mod_version=0.4.2
mod_authors=Atsuishio, Roki27, Light_Quanta mod_authors=Atsuishio, Roki27, Light_Quanta

View file

@ -18,6 +18,7 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import org.joml.Math;
import software.bernie.geckolib.animatable.GeoBlockEntity; import software.bernie.geckolib.animatable.GeoBlockEntity;
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache; import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.core.animation.AnimatableManager; import software.bernie.geckolib.core.animation.AnimatableManager;
@ -54,12 +55,12 @@ public class ContainerBlockEntity extends BlockEntity implements GeoBlockEntity
} }
} else { } else {
if (blockEntity.entity != null) { 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); pLevel.addFreshEntity(blockEntity.entity);
} else if (blockEntity.entityType != null) { } else if (blockEntity.entityType != null) {
var entity = blockEntity.entityType.create(pLevel); var entity = blockEntity.entityType.create(pLevel);
if (entity != null) { 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); pLevel.addFreshEntity(entity);
} }
} }

View file

@ -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");
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -9,6 +9,7 @@ import com.atsuishio.superbwarfare.init.ModEntities;
import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModSounds; import com.atsuishio.superbwarfare.init.ModSounds;
import com.atsuishio.superbwarfare.item.Monitor; import com.atsuishio.superbwarfare.item.Monitor;
import com.atsuishio.superbwarfare.tools.ChunkLoadTool;
import com.atsuishio.superbwarfare.tools.CustomExplosion; import com.atsuishio.superbwarfare.tools.CustomExplosion;
import com.atsuishio.superbwarfare.tools.EntityFindUtil; import com.atsuishio.superbwarfare.tools.EntityFindUtil;
import com.atsuishio.superbwarfare.tools.ParticleTool; 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.core.animation.AnimatableManager;
import software.bernie.geckolib.util.GeckoLibUtil; import software.bernie.geckolib.util.GeckoLibUtil;
import java.util.Comparator; import java.util.*;
import java.util.Objects;
import java.util.UUID;
public class DroneEntity extends MobileVehicleEntity implements GeoEntity { public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
public static final EntityDataAccessor<Boolean> LINKED = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.BOOLEAN); 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<String> CONTROLLER = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.STRING);
public static final EntityDataAccessor<Integer> AMMO = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.INT); 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 double lastTickVerticalSpeed;
public float pitch; public float pitch;
public float pitchO; public float pitchO;
public Set<Long> loadedChunks = new HashSet<>();
public DroneEntity(PlayMessages.SpawnEntity packet, Level world) { public DroneEntity(PlayMessages.SpawnEntity packet, Level world) {
this(ModEntities.DRONE.get(), 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.putString("Controller", this.entityData.get(CONTROLLER));
compound.putInt("Ammo", this.entityData.get(AMMO)); compound.putInt("Ammo", this.entityData.get(AMMO));
compound.putBoolean("Kamikaze", this.entityData.get(KAMIKAZE)); compound.putBoolean("Kamikaze", this.entityData.get(KAMIKAZE));
compound.putInt("Kamikaze", this.entityData.get(KAMIKAZE_MODE)); compound.putInt("KamikazeMode", this.entityData.get(KAMIKAZE_MODE));
} }
@Override @Override
@ -170,6 +171,11 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
super.baseTick(); super.baseTick();
if (this.level() instanceof ServerLevel serverLevel) {
// 更新需要加载的区块
ChunkLoadTool.updateLoadedChunks(serverLevel, this, this.loadedChunks);
}
lastTickSpeed = this.getDeltaMovement().length(); lastTickSpeed = this.getDeltaMovement().length();
lastTickVerticalSpeed = this.getDeltaMovement().y; 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)); Player controller = EntityFindUtil.findPlayer(this.level(), this.entityData.get(CONTROLLER));
if (!this.onGround()) { if (!this.onGround()) {
if (controller != null) { if (controller != null) {
handleSimulationDistance(controller);
ItemStack stack = controller.getMainHandItem(); ItemStack stack = controller.getMainHandItem();
if (stack.is(ModItems.MONITOR.get())) { if (stack.is(ModItems.MONITOR.get())) {
if (stack.getOrCreateTag().getBoolean("Using") && controller.level().isClientSide) { if (stack.getOrCreateTag().getBoolean("Using") && controller.level().isClientSide) {
@ -198,6 +204,15 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
if (!controller.level().isClientSide) { if (!controller.level().isClientSide) {
this.level().playSound(null, this.getOnPos(), ModSounds.DRONE_SOUND.get(), SoundSource.AMBIENT, 3, 1); 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(); 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() { public float getPropellerRot() {
return this.propellerRot; return this.propellerRot;
} }
@ -427,14 +461,13 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
hitEntityCrash(controller, target); hitEntityCrash(controller, target);
} }
} }
} }
public void hitEntityCrash(Player controller, Entity target) { public void hitEntityCrash(Player controller, Entity target) {
if (lastTickSpeed > 0.12) { if (lastTickSpeed > 0.12) {
if (this.entityData.get(KAMIKAZE) && 20 * lastTickSpeed > this.getHealth()) { if (this.entityData.get(KAMIKAZE) && 20 * lastTickSpeed > this.getHealth()) {
target.hurt(ModDamageTypes.causeCustomExplosionDamage(this.level().registryAccess(), this, controller), ExplosionConfig.DRONE_KAMIKAZE_HIT_DAMAGE.get()); 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); Monitor.disLink(controller.getMainHandItem(), controller);
} }
} }
@ -464,7 +497,6 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
@Override @Override
public void destroy() { public void destroy() {
String id = this.entityData.get(CONTROLLER); String id = this.entityData.get(CONTROLLER);
UUID uuid; UUID uuid;
try { try {
@ -539,4 +571,22 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
public AnimatableInstanceCache getAnimatableInstanceCache() { public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.cache; 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();
}
} }

View file

@ -5,6 +5,7 @@ import com.atsuishio.superbwarfare.config.server.ExplosionDestroyConfig;
import com.atsuishio.superbwarfare.entity.AnimatedEntity; import com.atsuishio.superbwarfare.entity.AnimatedEntity;
import com.atsuishio.superbwarfare.init.*; import com.atsuishio.superbwarfare.init.*;
import com.atsuishio.superbwarfare.network.message.ClientIndicatorMessage; import com.atsuishio.superbwarfare.network.message.ClientIndicatorMessage;
import com.atsuishio.superbwarfare.tools.ChunkLoadTool;
import com.atsuishio.superbwarfare.tools.CustomExplosion; import com.atsuishio.superbwarfare.tools.CustomExplosion;
import com.atsuishio.superbwarfare.tools.ParticleTool; import com.atsuishio.superbwarfare.tools.ParticleTool;
import com.atsuishio.superbwarfare.tools.ProjectileTool; 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.LivingEntity;
import net.minecraft.world.entity.projectile.ThrowableItemProjectile; import net.minecraft.world.entity.projectile.ThrowableItemProjectile;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block; 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.EntityHitResult;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.world.ForgeChunkManager;
import net.minecraftforge.network.NetworkHooks; import net.minecraftforge.network.NetworkHooks;
import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.PlayMessages; 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); public static final EntityDataAccessor<String> ANIMATION = SynchedEntityData.defineId(CannonShellEntity.class, EntityDataSerializers.STRING);
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
public String animationprocedure = "empty"; public String animationProcedure = "empty";
private float damage = 0; private float damage = 0;
private float radius = 0; private float radius = 0;
private float explosionDamage = 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, ParticleTool.sendParticle(serverLevel, ParticleTypes.SMOKE, this.xo, this.yo, this.zo,
1, 0, 0, 0, 0.001, true); 1, 0, 0, 0, 0.001, true);
var movement = this.getDeltaMovement(); // 更新需要加载的区块
var currentX = this.chunkPosition().x; ChunkLoadTool.updateLoadedChunks(serverLevel, this, this.loadedChunks);
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));
} }
if (this.tickCount > 600 || this.isInWater()) { if (this.tickCount > 600 || this.isInWater()) {
if (this.level() instanceof ServerLevel) { if (this.level() instanceof ServerLevel) {
@ -353,20 +339,20 @@ public class CannonShellEntity extends ThrowableItemProjectile implements GeoEnt
} }
private PlayState movementPredicate(AnimationState<CannonShellEntity> event) { 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 event.setAndContinue(RawAnimation.begin().thenLoop("animation.cannon_shell.idle"));
} }
return PlayState.STOP; return PlayState.STOP;
} }
private PlayState procedurePredicate(AnimationState<CannonShellEntity> event) { private PlayState procedurePredicate(AnimationState<CannonShellEntity> event) {
if (!animationprocedure.equals("empty") && event.getController().getAnimationState() == AnimationController.State.STOPPED) { if (!animationProcedure.equals("empty") && event.getController().getAnimationState() == AnimationController.State.STOPPED) {
event.getController().setAnimation(RawAnimation.begin().thenPlay(this.animationprocedure)); event.getController().setAnimation(RawAnimation.begin().thenPlay(this.animationProcedure));
if (event.getController().getAnimationState() == AnimationController.State.STOPPED) { if (event.getController().getAnimationState() == AnimationController.State.STOPPED) {
this.animationprocedure = "empty"; this.animationProcedure = "empty";
event.getController().forceAnimationReset(); event.getController().forceAnimationReset();
} }
} else if (animationprocedure.equals("empty")) { } else if (animationProcedure.equals("empty")) {
return PlayState.STOP; return PlayState.STOP;
} }
return PlayState.CONTINUE; return PlayState.CONTINUE;
@ -387,7 +373,7 @@ public class CannonShellEntity extends ThrowableItemProjectile implements GeoEnt
@Override @Override
public void setAnimationProcedure(String procedure) { public void setAnimationProcedure(String procedure) {
this.animationprocedure = procedure; this.animationProcedure = procedure;
} }
@Override @Override
@ -404,9 +390,7 @@ public class CannonShellEntity extends ThrowableItemProjectile implements GeoEnt
@Override @Override
public void onRemovedFromWorld() { public void onRemovedFromWorld() {
if (this.level() instanceof ServerLevel serverLevel) { if (this.level() instanceof ServerLevel serverLevel) {
for (long chunkPos : this.loadedChunks) { ChunkLoadTool.unloadAllChunks(serverLevel, this, this.loadedChunks);
ForgeChunkManager.forceChunk(serverLevel, ModUtils.MODID, this, ChunkPos.getX(chunkPos), ChunkPos.getZ(chunkPos), false, false);
}
} }
super.onRemovedFromWorld(); super.onRemovedFromWorld();
} }

View file

@ -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;
}
}

View file

@ -1,10 +1,10 @@
package com.atsuishio.superbwarfare.entity.projectile; package com.atsuishio.superbwarfare.entity.projectile;
import com.atsuishio.superbwarfare.ModUtils;
import com.atsuishio.superbwarfare.config.server.ExplosionConfig; import com.atsuishio.superbwarfare.config.server.ExplosionConfig;
import com.atsuishio.superbwarfare.init.ModDamageTypes; import com.atsuishio.superbwarfare.init.ModDamageTypes;
import com.atsuishio.superbwarfare.init.ModEntities; import com.atsuishio.superbwarfare.init.ModEntities;
import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.tools.ChunkLoadTool;
import com.atsuishio.superbwarfare.tools.ParticleTool; import com.atsuishio.superbwarfare.tools.ParticleTool;
import com.atsuishio.superbwarfare.tools.ProjectileTool; import com.atsuishio.superbwarfare.tools.ProjectileTool;
import net.minecraft.core.BlockPos; 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.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.EntityHitResult;
import net.minecraftforge.common.world.ForgeChunkManager;
import net.minecraftforge.network.NetworkHooks; import net.minecraftforge.network.NetworkHooks;
import net.minecraftforge.network.PlayMessages; import net.minecraftforge.network.PlayMessages;
import software.bernie.geckolib.animatable.GeoEntity; 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, ParticleTool.sendParticle(serverLevel, ParticleTypes.CAMPFIRE_COSY_SMOKE, this.xo, this.yo, this.zo,
1, 0, 0, 0, 0.001, true); 1, 0, 0, 0, 0.001, true);
var movement = this.getDeltaMovement(); // 更新需要加载的区块
var currentX = this.chunkPosition().x; ChunkLoadTool.updateLoadedChunks(serverLevel, this, this.loadedChunks);
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));
} }
if (this.tickCount > this.life || this.isInWater()) { if (this.tickCount > this.life || this.isInWater()) {
if (this.level() instanceof ServerLevel) { if (this.level() instanceof ServerLevel) {
@ -199,9 +185,7 @@ public class MortarShellEntity extends ThrowableItemProjectile implements GeoEnt
@Override @Override
public void onRemovedFromWorld() { public void onRemovedFromWorld() {
if (this.level() instanceof ServerLevel serverLevel) { if (this.level() instanceof ServerLevel serverLevel) {
for (long chunkPos : this.loadedChunks) { ChunkLoadTool.unloadAllChunks(serverLevel, this, this.loadedChunks);
ForgeChunkManager.forceChunk(serverLevel, ModUtils.MODID, this, ChunkPos.getX(chunkPos), ChunkPos.getZ(chunkPos), false, false);
}
} }
super.onRemovedFromWorld(); super.onRemovedFromWorld();
} }

View file

@ -51,7 +51,7 @@ public class RpgRocketEntity extends ThrowableItemProjectile implements GeoEntit
public static final EntityDataAccessor<String> ANIMATION = SynchedEntityData.defineId(RpgRocketEntity.class, EntityDataSerializers.STRING); public static final EntityDataAccessor<String> ANIMATION = SynchedEntityData.defineId(RpgRocketEntity.class, EntityDataSerializers.STRING);
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
public String animationprocedure = "empty"; public String animationProcedure = "empty";
private float monsterMultiplier = 0.0f; private float monsterMultiplier = 0.0f;
private float damage = 250f; private float damage = 250f;
@ -205,7 +205,7 @@ public class RpgRocketEntity extends ThrowableItemProjectile implements GeoEntit
@Override @Override
public void setAnimationProcedure(String procedure) { public void setAnimationProcedure(String procedure) {
this.animationprocedure = procedure; this.animationProcedure = procedure;
} }
@Override @Override

View file

@ -154,6 +154,8 @@ public class Ah6Entity extends ContainerMobileEntity implements GeoEntity, IHeli
propellerRotO = this.getPropellerRot(); propellerRotO = this.getPropellerRot();
super.baseTick(); super.baseTick();
setZRot(getRoll() * 0.995f);
if (heat > 0) { if (heat > 0) {
heat--; 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.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.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.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.level() instanceof ServerLevel) {
if (this.getEnergy() > 0) { if (this.getEnergy() > 0) {
boolean up = this.upInputDown || this.forwardInputDown; boolean up = upInputDown || forwardInputDown;
boolean down = this.downInputDown || this.backInputDown; boolean down = this.downInputDown;
if (!engineStart && up) { if (!engineStart && up) {
engineStart = true; 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)); this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + 0.002f, 0.12f));
} }
if (down && engineStartOver) { if (engineStartOver) {
this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - 0.0015f, this.onGround() ? 0 : 0.0375f)); 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) { if (engineStart && !engineStartOver) {
this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + 0.0012f, 0.045f)); 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) { 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 { } 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 { } 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)); 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)); 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)); 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) { if (this.entityData.get(POWER) > 0.04f) {
engineStartOver = true; engineStartOver = true;
@ -396,10 +405,6 @@ public class Ah6Entity extends ContainerMobileEntity implements GeoEntity, IHeli
Vector4f worldPosition = transformPosition(transform, x, y, z); Vector4f worldPosition = transformPosition(transform, x, y, z);
passenger.setPos(worldPosition.x, worldPosition.y, worldPosition.z); passenger.setPos(worldPosition.x, worldPosition.y, worldPosition.z);
callback.accept(passenger, 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()) { if (passenger != this.getFirstPassenger()) {
@ -412,7 +417,6 @@ public class Ah6Entity extends ContainerMobileEntity implements GeoEntity, IHeli
public void copyEntityData(Entity entity) { public void copyEntityData(Entity entity) {
float f = Mth.wrapDegrees(entity.getYRot() - getYRot()); float f = Mth.wrapDegrees(entity.getYRot() - getYRot());
float g = Mth.clamp(f, -105.0f, 105.0f); float g = Mth.clamp(f, -105.0f, 105.0f);
entity.yRotO += g - f; entity.yRotO += g - f;
entity.setYRot(entity.getYRot() + g - f); entity.setYRot(entity.getYRot() + g - f);
entity.setYHeadRot(entity.getYRot()); entity.setYHeadRot(entity.getYRot());

View file

@ -257,11 +257,12 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
this.setDeltaMovement(this.getDeltaMovement().add(0.0, fluidFloat, 0.0)); this.setDeltaMovement(this.getDeltaMovement().add(0.0, fluidFloat, 0.0));
if (this.onGround()) { 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().add(this.getViewVector(1).normalize().scale(0.05 * this.getDeltaMovement().horizontalDistance())));
this.setDeltaMovement(this.getDeltaMovement().multiply(f0, 0.85, f0)); this.setDeltaMovement(this.getDeltaMovement().multiply(f0, 0.85, f0));
} else if (this.isInWater()) { } 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().add(this.getViewVector(1).normalize().scale(0.04 * this.getDeltaMovement().horizontalDistance())));
this.setDeltaMovement(this.getDeltaMovement().multiply(f1, 0.85, f1)); this.setDeltaMovement(this.getDeltaMovement().multiply(f1, 0.85, f1));
} else { } else {
@ -483,11 +484,11 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
} }
if (forwardInputDown) { 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) { 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) { if (rightInputDown) {
@ -500,7 +501,7 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
this.extraEnergy(VehicleConfig.SPEEDBOAT_ENERGY_COST.get()); 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)); 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)); 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); this.setRudderRot(Mth.clamp(this.getRudderRot() - this.entityData.get(DELTA_ROT), -0.8f, 0.8f) * 0.75f);
if (this.isInWater() || onGround()) { 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.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.3f : 1) * this.entityData.get(POWER), 0.0, Mth.cos(this.getYRot() * 0.017453292F) * (isInWater() && !onGround() ? 0.3f : 1) * this.entityData.get(POWER))); 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)));
} }
} }

View file

@ -68,6 +68,7 @@ public class MobileVehicleEntity extends EnergyVehicleEntity {
collisionCoolDown--; collisionCoolDown--;
} }
super.baseTick(); super.baseTick();
preventStacking();
crushEntities(this.getDeltaMovement()); crushEntities(this.getDeltaMovement());
this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.06, 0.0)); this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.06, 0.0));
this.move(MoverType.SELF, this.getDeltaMovement()); this.move(MoverType.SELF, this.getDeltaMovement());
@ -100,16 +101,17 @@ public class MobileVehicleEntity extends EnergyVehicleEntity {
} }
collisionCoolDown = 4; collisionCoolDown = 4;
crash = true; crash = true;
this.entityData.set(POWER, 0.4f * entityData.get(POWER));
} }
} }
public void bounceHorizontal(Direction direction) { public void bounceHorizontal(Direction direction) {
switch (direction.getAxis()) { switch (direction.getAxis()) {
case X: 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; break;
case Z: 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; 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 动量 * @param velocity 动量
*/ */
public void crushEntities(Vec3 velocity) { public void crushEntities(Vec3 velocity) {
if (this instanceof DroneEntity) return; if (this instanceof DroneEntity) return;
if (velocity.horizontalDistance() < 0.1) return; if (velocity.horizontalDistance() < 0.25) return;
if (isRemoved()) return; if (isRemoved()) return;
var frontBox = getBoundingBox().move(velocity.scale(0.5)); var frontBox = getBoundingBox().move(velocity.scale(0.5));
var velAdd = velocity.add(0, 0, 0).scale(0.9); 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 f = Math.min(entitySize / thisSize, 2);
double f1 = Math.min(thisSize / entitySize, 4); 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) { if (!this.level().isClientSide) {
this.level().playSound(null, this, ModSounds.VEHICLE_STRIKE.get(), this.getSoundSource(), 1, 1); this.level().playSound(null, this, ModSounds.VEHICLE_STRIKE.get(), this.getSoundSource(), 1, 1);
} }

View file

@ -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;
}
}

View file

@ -239,7 +239,6 @@ public class VehicleEntity extends Entity {
lastHurtTick ++; lastHurtTick ++;
prevRoll = this.getRoll(); prevRoll = this.getRoll();
setZRot(roll * 0.9f);
float delta = Math.abs(getYRot() - yRotO); float delta = Math.abs(getYRot() - yRotO);
while (getYRot() > 180F) { while (getYRot() > 180F) {

View file

@ -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)); 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", 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)); 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) { private static <T extends Entity> RegistryObject<EntityType<T>> register(String name, EntityType.Builder<T> entityTypeBuilder) {
return REGISTRY.register(name, () -> entityTypeBuilder.build(name)); return REGISTRY.register(name, () -> entityTypeBuilder.build(name));

View file

@ -37,5 +37,7 @@ public class ModEntityRenderers {
event.registerEntityRenderer(ModEntities.FLARE_DECOY.get(), FlareDecoyEntityRenderer::new); event.registerEntityRenderer(ModEntities.FLARE_DECOY.get(), FlareDecoyEntityRenderer::new);
event.registerEntityRenderer(ModEntities.LAV_150.get(), Lav150Renderer::new); event.registerEntityRenderer(ModEntities.LAV_150.get(), Lav150Renderer::new);
event.registerEntityRenderer(ModEntities.SMALL_CANNON_SHELL.get(), SmallCannonShellRenderer::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);
} }
} }

View file

@ -110,6 +110,7 @@ public class ModTabs {
output.accept(ContainerBlockItem.createInstance(ModEntities.WHEEL_CHAIR.get())); output.accept(ContainerBlockItem.createInstance(ModEntities.WHEEL_CHAIR.get()));
output.accept(ContainerBlockItem.createInstance(ModEntities.AH_6.get())); output.accept(ContainerBlockItem.createInstance(ModEntities.AH_6.get()));
output.accept(ContainerBlockItem.createInstance(ModEntities.LAV_150.get())); output.accept(ContainerBlockItem.createInstance(ModEntities.LAV_150.get()));
output.accept(ContainerBlockItem.createInstance(ModEntities.TOM_6.get()));
} else { } else {
output.accept(registryObject.get()); output.accept(registryObject.get());
if (registryObject.get() == ModItems.ARMOR_PLATE.get()) { if (registryObject.get() == ModItems.ARMOR_PLATE.get()) {

View file

@ -21,6 +21,7 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
@ -104,6 +105,12 @@ public class Monitor extends Item {
return super.getAttributeModifiers(slot, stack); 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) @OnlyIn(Dist.CLIENT)
@Override @Override
public void appendHoverText(ItemStack stack, Level world, List<Component> list, TooltipFlag flag) { 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; Player player = Minecraft.getInstance().player;
if (player == null) return; if (player == null) return;
DroneEntity drone = EntityFindUtil.findDrone(player.level(), stack.getOrCreateTag().getString(LINKED_DRONE)); Vec3 droneVec = new Vec3(stack.getOrCreateTag().getDouble("PosX"), stack.getOrCreateTag().getDouble("PosY"), stack.getOrCreateTag().getDouble("PosZ"));
if (drone == null) return;
list.add(Component.translatable("des.superbwarfare.monitor", list.add(Component.translatable("des.superbwarfare.monitor",new DecimalFormat("##.#").format(player.position().distanceTo(droneVec)) + "m").withStyle(ChatFormatting.GRAY));
new DecimalFormat("##.#").format(player.distanceTo(drone)) + "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 @Override

View file

@ -294,7 +294,7 @@ public class ReforgingTableMenu extends AbstractContainerMenu {
ItemStack output = gun.copy(); ItemStack output = gun.copy();
PerkHelper.removePerkByType(output, perkItem.getPerk().type); PerkHelper.removePerkByType(output, perkItem.getPerk().type);
GunsTool.setGunDoubleTag(output, "UpgradePoint", Math.min(MAX_UPGRADE_POINT, level - 1 + GunsTool.getGunDoubleTag(output, "UpgradePoint", 0))); 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.setItem(INPUT_SLOT, output);
this.container.setChanged(); this.container.setChanged();

View file

@ -128,6 +128,11 @@ public abstract class CameraMixin {
return; return;
} }
if (thirdPerson && entity.getVehicle() instanceof Tom6Entity) {
move(-getMaxZoom(4), 1, 0);
return;
}
if (thirdPerson && entity.getVehicle() instanceof Lav150Entity && !ClientEventHandler.zoomVehicle) { if (thirdPerson && entity.getVehicle() instanceof Lav150Entity && !ClientEventHandler.zoomVehicle) {
move(-getMaxZoom(2.75), 1, 0.0); move(-getMaxZoom(2.75), 1, 0.0);
return; return;

View file

@ -1,6 +1,7 @@
package com.atsuishio.superbwarfare.mixins; package com.atsuishio.superbwarfare.mixins;
import com.atsuishio.superbwarfare.entity.vehicle.Ah6Entity; import com.atsuishio.superbwarfare.entity.vehicle.Ah6Entity;
import com.atsuishio.superbwarfare.entity.vehicle.Tom6Entity;
import com.atsuishio.superbwarfare.init.ModTags; import com.atsuishio.superbwarfare.init.ModTags;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis; import com.mojang.math.Axis;
@ -69,5 +70,30 @@ public class GameRendererMixin {
matrices.mulPose(Axis.YP.rotationDegrees(-mainCamera.getYRot() - 180.0f)); matrices.mulPose(Axis.YP.rotationDegrees(-mainCamera.getYRot() - 180.0f));
matrices.mulPose(Axis.XP.rotationDegrees(-mainCamera.getXRot())); 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()));
}
} }
} }

View file

@ -1,6 +1,7 @@
package com.atsuishio.superbwarfare.mixins; package com.atsuishio.superbwarfare.mixins;
import com.atsuishio.superbwarfare.entity.vehicle.Ah6Entity; import com.atsuishio.superbwarfare.entity.vehicle.Ah6Entity;
import com.atsuishio.superbwarfare.entity.vehicle.Tom6Entity;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis; import com.mojang.math.Axis;
import net.minecraft.client.renderer.entity.LivingEntityRenderer; 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.XP.rotationDegrees(-ah6Entity.getViewXRot(tickDelta)));
matrices.mulPose(Axis.ZP.rotationDegrees(-ah6Entity.getRoll(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)));
}
} }
} }

View file

@ -4,6 +4,7 @@ import com.atsuishio.superbwarfare.config.client.VehicleControlConfig;
import com.atsuishio.superbwarfare.entity.vehicle.Ah6Entity; import com.atsuishio.superbwarfare.entity.vehicle.Ah6Entity;
import com.atsuishio.superbwarfare.entity.vehicle.ICannonEntity; import com.atsuishio.superbwarfare.entity.vehicle.ICannonEntity;
import com.atsuishio.superbwarfare.entity.vehicle.Lav150Entity; import com.atsuishio.superbwarfare.entity.vehicle.Lav150Entity;
import com.atsuishio.superbwarfare.entity.vehicle.Tom6Entity;
import com.atsuishio.superbwarfare.event.ClientEventHandler; import com.atsuishio.superbwarfare.event.ClientEventHandler;
import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModMobEffects; 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.CameraType;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.MouseHandler; import net.minecraft.client.MouseHandler;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
@ -78,7 +80,11 @@ public class MouseHandlerMixin {
if (player == null) return i; if (player == null) return i;
if (player.getVehicle() instanceof Ah6Entity ah6Entity && ah6Entity.getFirstPassenger() == player) { 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; return i;
} }

View file

@ -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);
});
}
}

File diff suppressed because it is too large Load diff

View file

@ -401,6 +401,8 @@
"entity.superbwarfare.ah_6": "AH-6 Little Bird", "entity.superbwarfare.ah_6": "AH-6 Little Bird",
"entity.superbwarfare.lav_150": "LAV-150 Commando", "entity.superbwarfare.lav_150": "LAV-150 Commando",
"entity.minecraft.villager.superbwarfare.armory": "Armory", "entity.minecraft.villager.superbwarfare.armory": "Armory",
"entity.superbwarfare.tom_6": "Tom F6F",
"entity.superbwarfare.melon_bomb": "Melon Bomb",
"key.categories.superbwarfare": "Superb Warfare", "key.categories.superbwarfare": "Superb Warfare",
"key.superbwarfare.hold_zoom": "Zoom(Hold)", "key.superbwarfare.hold_zoom": "Zoom(Hold)",

View file

@ -399,6 +399,8 @@
"entity.superbwarfare.ah_6": "AH-6 小鸟直升机", "entity.superbwarfare.ah_6": "AH-6 小鸟直升机",
"entity.superbwarfare.lav_150": "LAV-150 Commando", "entity.superbwarfare.lav_150": "LAV-150 Commando",
"entity.minecraft.villager.superbwarfare.armory": "军械师", "entity.minecraft.villager.superbwarfare.armory": "军械师",
"entity.superbwarfare.tom_6": "汤姆 F6F",
"entity.superbwarfare.melon_bomb": "西瓜航弹",
"key.categories.superbwarfare": "卓越前线", "key.categories.superbwarfare": "卓越前线",
"key.superbwarfare.hold_zoom": "瞄准(按住)", "key.superbwarfare.hold_zoom": "瞄准(按住)",

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB