From a61e578863888be0e51fdbf2e5c7684f1c86d33b Mon Sep 17 00:00:00 2001 From: Garfield Date: Wed, 2 Sep 2020 22:30:37 +0200 Subject: [PATCH] Sloppy flying --- .../github/MinecraftSpaceProgram/MSP/MSP.java | 1 + .../renderer/entity/RocketRenderer.java | 27 +- .../MSP/entity/RocketEntity.java | 866 +++++++++--------- .../MSP/entity/RocketEntityType.java | 2 +- .../MSP/init/MSPDataSerializers.java | 74 ++ .../MSP/physics/orbital/PhysicsUtil.java | 5 + .../MSP/rocket/Rocket.java | 1 - .../MSP/util/BlockStorage.java | 21 +- 8 files changed, 537 insertions(+), 460 deletions(-) create mode 100644 src/main/java/io/github/MinecraftSpaceProgram/MSP/init/MSPDataSerializers.java diff --git a/src/main/java/io/github/MinecraftSpaceProgram/MSP/MSP.java b/src/main/java/io/github/MinecraftSpaceProgram/MSP/MSP.java index 03a7799..24ea05b 100644 --- a/src/main/java/io/github/MinecraftSpaceProgram/MSP/MSP.java +++ b/src/main/java/io/github/MinecraftSpaceProgram/MSP/MSP.java @@ -44,6 +44,7 @@ public MSP() { MSPTileEntityTypes.TILE_ENTITY_TYPES.register(modEventBus); MSPEntityTypes.ENTITY_TYPES.register(modEventBus); ModContainerTypes.CONTAINER_TYPES.register(modEventBus); + MSPDataSerializers.DATA_SERIALIZERS.register(modEventBus); } @SubscribeEvent diff --git a/src/main/java/io/github/MinecraftSpaceProgram/MSP/client/renderer/entity/RocketRenderer.java b/src/main/java/io/github/MinecraftSpaceProgram/MSP/client/renderer/entity/RocketRenderer.java index 9ebe92f..1815c41 100644 --- a/src/main/java/io/github/MinecraftSpaceProgram/MSP/client/renderer/entity/RocketRenderer.java +++ b/src/main/java/io/github/MinecraftSpaceProgram/MSP/client/renderer/entity/RocketRenderer.java @@ -5,19 +5,17 @@ import io.github.MinecraftSpaceProgram.MSP.entity.RocketEntity; import io.github.MinecraftSpaceProgram.MSP.util.BlockStorage; import mcp.MethodsReturnNonnullByDefault; -import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockRendererDispatcher; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererManager; import net.minecraft.client.renderer.texture.AtlasTexture; import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.entity.item.FallingBlockEntity; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3f; -import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -42,30 +40,17 @@ public void render(RocketEntity entity, float entityYaw, float partialTicks, Mat matrixStack.push(); matrixStack.rotate(Vector3f.YP.rotationDegrees(entity.getYaw(partialTicks))); //Render Each block - World world = entity.getWorldObj(); + BlockRendererDispatcher BLOCK_RENDERER = Minecraft.getInstance().getBlockRendererDispatcher(); for (int xx = 0; xx < storage.sizeX; xx++) { for (int zz = 0; zz < storage.sizeZ; zz++) { for (int yy = 0; yy < storage.sizeY; yy++) { BlockState blockState = storage.getBlockState(new BlockPos(xx, yy, zz)); if (blockState != null) { try { - FallingBlockEntity entityIn = new FallingBlockEntity( - world, - entity.getPosX(), - entity.getPosY(), - entity.getPosZ(), - blockState - ); - - BlockState blockstate = entityIn.getBlockState(); - if (blockstate.getRenderType() == BlockRenderType.MODEL) { - if (blockstate != world.getBlockState(entityIn.func_233580_cy_()) && blockstate.getRenderType() != BlockRenderType.INVISIBLE) { - matrixStack.push(); - matrixStack.translate(xx, yy, zz); - Minecraft.getInstance().getBlockRendererDispatcher().renderBlock(blockState, matrixStack, bufferIn, packedLightIn, OverlayTexture.NO_OVERLAY); - matrixStack.pop(); - } - } + matrixStack.push(); + matrixStack.translate(xx - 0.5D, yy, zz - 0.5D); + BLOCK_RENDERER.renderBlock(blockState, matrixStack, bufferIn, packedLightIn, OverlayTexture.NO_OVERLAY); + matrixStack.pop(); } catch (NullPointerException e) { MSP.LOGGER.debug(blockState.getBlock().getRegistryName() + " cannot be rendered on rocket at " + entity.getPositionVec()); } diff --git a/src/main/java/io/github/MinecraftSpaceProgram/MSP/entity/RocketEntity.java b/src/main/java/io/github/MinecraftSpaceProgram/MSP/entity/RocketEntity.java index 26166e1..37eac4d 100644 --- a/src/main/java/io/github/MinecraftSpaceProgram/MSP/entity/RocketEntity.java +++ b/src/main/java/io/github/MinecraftSpaceProgram/MSP/entity/RocketEntity.java @@ -3,13 +3,13 @@ import io.github.MinecraftSpaceProgram.MSP.MSP; import io.github.MinecraftSpaceProgram.MSP.init.MSPBlocks; import io.github.MinecraftSpaceProgram.MSP.init.MSPEntityTypes; +import io.github.MinecraftSpaceProgram.MSP.physics.orbital.SolarSystem; import io.github.MinecraftSpaceProgram.MSP.util.BlockStorage; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.entity.*; import net.minecraft.entity.item.BoatEntity; import net.minecraft.entity.passive.AnimalEntity; -import net.minecraft.entity.passive.WaterMobEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; @@ -18,10 +18,12 @@ import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.particles.ParticleTypes; import net.minecraft.util.*; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Quaternion; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.GameRules; import net.minecraft.world.World; @@ -35,447 +37,445 @@ import javax.annotation.ParametersAreNonnullByDefault; import java.util.List; +import static io.github.MinecraftSpaceProgram.MSP.init.MSPDataSerializers.QUATERNION_SERIALIZER; +import static io.github.MinecraftSpaceProgram.MSP.physics.orbital.PhysicsUtil.G; +import static io.github.MinecraftSpaceProgram.MSP.physics.orbital.PhysicsUtil.TICK_LENGTH; + @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault public class RocketEntity extends Entity implements IEntityAdditionalSpawnData { - protected static final DataParameter FUEL = EntityDataManager.createKey(RocketEntity.class, DataSerializers.VARINT); - //private static final DataParameter STORAGE = EntityDataManager.createKey(RocketEntity.class, DataSerializers.BLOCK_POS); - public BlockStorage storage; - private float momentum; - private float deltaRotation; - private int lerpSteps; - private double lerpX; - private double lerpY; - private double lerpZ; - private double lerpYaw; - private double lerpPitch; - private boolean leftInputDown; - private boolean rightInputDown; - private boolean forwardInputDown; - private boolean backInputDown; - private float boatGlide; - - public RocketEntity(EntityType entityEntityType, World world) { - super(entityEntityType, world); - MSP.LOGGER.debug("SUMMONED A ROCKET"); - this.storage = new BlockStorage( - new BlockState[][][]{{{MSPBlocks.ROCKET_GENERIC.get().getDefaultState()}}}, - 1, - 1, - 1, - 1, - 1, - 1, - 1 - ); - } - - public RocketEntity(World world, BlockStorage storage, double x, double y, double z) { - super(MSPEntityTypes.ROCKET_ENTITY_TYPE.get(), world); - this.storage = storage; - this.setPosition(x, y, z); - } - - @Override - public void tick() { - - super.tick(); - this.tickLerp(); - if (this.canPassengerSteer()) { - this.updateMotion(); - if (this.world.isRemote) { - this.controlBoat(); - } - - this.move(MoverType.SELF, this.getMotion()); - } else { - this.setMotion(Vector3d.ZERO); - } - - this.doBlockCollisions(); - List list = this.world.getEntitiesInAABBexcluding(this, this.getBoundingBox().grow( 0.2F, -0.01F,0.2F), EntityPredicates.pushableBy(this)); - if (!list.isEmpty()) { - boolean flag = !this.world.isRemote && !(this.getControllingPassenger() instanceof PlayerEntity); - - for (Entity entity : list) { - if (!entity.isPassenger(this)) { - if (flag && this.getPassengers().size() < 2 && !entity.isPassenger() && entity.getWidth() < this.getWidth() && entity instanceof LivingEntity && !(entity instanceof WaterMobEntity) && !(entity instanceof PlayerEntity)) { - entity.startRiding(this); - } else { - this.applyEntityCollision(entity); - } - } - } - } - - } - - private void tickLerp() { - if (this.canPassengerSteer()) { - this.lerpSteps = 0; - this.setPacketCoordinates(this.getPosX(), this.getPosY(), this.getPosZ()); - } - - if (this.lerpSteps > 0) { - double d0 = this.getPosX() + (this.lerpX - this.getPosX()) / (double) this.lerpSteps; - double d1 = this.getPosY() + (this.lerpY - this.getPosY()) / (double) this.lerpSteps; - double d2 = this.getPosZ() + (this.lerpZ - this.getPosZ()) / (double) this.lerpSteps; - double d3 = MathHelper.wrapDegrees(this.lerpYaw - (double) this.rotationYaw); - this.rotationYaw = (float) ((double) this.rotationYaw + d3 / (double) this.lerpSteps); - this.rotationPitch = (float) ((double) this.rotationPitch + (this.lerpPitch - (double) this.rotationPitch) / (double) this.lerpSteps); - --this.lerpSteps; - this.setPosition(d0, d1, d2); - this.setRotation(this.rotationYaw, this.rotationPitch); + protected static final DataParameter STARTED = + EntityDataManager.createKey(RocketEntity.class, DataSerializers.BOOLEAN); + protected static final DataParameter FUEL = + EntityDataManager.createKey(RocketEntity.class, DataSerializers.FLOAT); + protected static final DataParameter QUATERNION = + EntityDataManager.createKey(RocketEntity.class, QUATERNION_SERIALIZER); + // private static final DataParameter STORAGE = + // EntityDataManager.createKey(RocketEntity.class, DataSerializers.BLOCK_POS); + + protected final AxisAlignedBB AABB; + public BlockStorage storage; + private int lerpSteps; + private double lerpX; + private double lerpY; + private double lerpZ; + private double lerpYaw; + private double lerpPitch; + + public RocketEntity(EntityType entityEntityType, World world) { + super(entityEntityType, world); + MSP.LOGGER.debug("SUMMONED A ROCKET"); + this.storage = + new BlockStorage( + new BlockState[][][] {{{MSPBlocks.ROCKET_GENERIC.get().getDefaultState()}}}, + 1, + 1, + 1, + 1, + 1, + 1, + 1); + + this.AABB = new AxisAlignedBB(0, 0, 0, 1, 1, 1); + } + + public RocketEntity(World world, BlockStorage storage, double x, double y, double z) { + super(MSPEntityTypes.ROCKET_ENTITY_TYPE.get(), world); + this.storage = storage; + this.setPosition(x, y, z); + this.AABB = new AxisAlignedBB(0, 0, 0, storage.sizeX, storage.sizeY, storage.sizeZ); + this.recalculateSize(); + // TODO only fuel tanks + this.dataManager.set(FUEL, (this.storage.numberOfBlocks - 1) * 1.0F); + } + + @Override + public void tick() { + super.tick(); + this.tickLerp(); + if (Double.isNaN(getMotion().length())) { + setMotion(Vector3d.ZERO); + } + + LivingEntity controllingPassenger = (LivingEntity) getControllingPassenger(); + float moveForward = + controllingPassenger instanceof PlayerEntity ? controllingPassenger.moveForward : 0; + if (moveForward > 0 && !dataManager.get(STARTED)) { + dataManager.set(STARTED, true); + } + + // TODO make this planet dependant + double r = this.getPosY() + SolarSystem.EARTH.size / 2.0D; + Vector3d previousMotion = + this.getMotion().add(0, -G * SolarSystem.EARTH.mass / (r * r) * TICK_LENGTH, 0); + MSP.LOGGER.debug(G * SolarSystem.EARTH.mass / (r * r)); + + // TODO currently using a monopropellant engine MR-80B 3,100N (700 lbf) Throttling Rocket from + // Aerojet Rocketdyne + if (dataManager.get(STARTED)) { + float fuel = dataManager.get(FUEL); + if (fuel > 0) { + fuel -= 0.1f * (float) TICK_LENGTH; + dataManager.set(FUEL, fuel); + previousMotion = + previousMotion.add( + 0, + 3100 + / (dataManager.get(FUEL) + 168 + 100 + 5 * storage.numberOfBlocks) + * TICK_LENGTH, + 0); + + if (world.isRemote) { + if (world.getGameTime() % 10 == 0) + spawnParticle( + "rocketSmoke", world, this.getPosX(), this.getPosY(), this.getPosZ(), 0, 0, 0); + + // TODO make this actually do flames + for (int i = 0; i < 4; i++) { + spawnParticle( + "rocketFlame", + world, + this.getPosX(), + this.getPosY() - 0.75 - 0.2 * i, + this.getPosZ(), + (this.rand.nextFloat() - 0.5f) / 8f, + -.75, + (this.rand.nextFloat() - 0.5f) / 8f); + } } - } - - @Override - protected void registerData() { - dataManager.register(FUEL, 0); - } - - public int getFuel() { - return dataManager.get(FUEL); - } - - public boolean isPowered() { - return dataManager.get(FUEL) > 0; - } - - @Override - protected void readAdditional(@Nonnull CompoundNBT compound) { - //this.storage = new BlockStorage(compound.getCompound("storage")); - } - - @Override - protected void writeAdditional(@Nonnull CompoundNBT compound) { - //compound.put("storage", this.storage.toNBT()); - } - - public BlockStorage getStorage() { - return storage; - } - - @OnlyIn(Dist.CLIENT) - public World getWorldObj() { - return this.world; - } - - @SuppressWarnings("deprecation") - @Override - public boolean attackEntityFrom(DamageSource source, float amount) { - if (this.isInvulnerableTo(source)) { - return false; - } - if (!(source.getTrueSource() instanceof PlayerEntity && ((PlayerEntity) source.getTrueSource()).abilities.isCreativeMode) - && world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS) && !this.removed) { - entityDropItem(Items.STICK); - } - if (!this.world.isRemote && !this.removed) { - remove(); - return true; - } - return false; - } - - /** - * Returns a boundingBox used to collide the entity with other entities and blocks. This enables the entity to be - * pushable on contact, like boats. - */ - @Nullable - @Override - public AxisAlignedBB getCollisionBox(Entity entityIn) { - return entityIn.canBePushed() ? entityIn.getBoundingBox() : null; - } - - /** - * Returns the solid collision bounding box for this entity. Used to make (e.g.) boats solid. Return null if - * this entity is not solid. - */ - @Nullable - @Override - public AxisAlignedBB getCollisionBoundingBox() { - return this.getBoundingBox(); - } - - /** - * Returns true if this entity should push and be pushed by other entities when colliding. - */ - @Override - public boolean canBePushed() { - return true; - } - - /** - * Returns the Y offset from the entity's position for any entity riding this one. - */ - //TODO SEATS - @Override - public double getMountedYOffset() { - return -0.1D; - } - - /** - * Applies a velocity to the entities, to push them away from eachother. - */ - @Override - public void applyEntityCollision(Entity entityIn) { - if (entityIn instanceof BoatEntity) { - if (entityIn.getBoundingBox().minY < this.getBoundingBox().maxY) { - super.applyEntityCollision(entityIn); - } - } else if (entityIn.getBoundingBox().minY <= this.getBoundingBox().minY) { - super.applyEntityCollision(entityIn); - } - } - - /** - * Returns true if other Entities should be prevented from moving through this Entity. - */ - @Override - public boolean canBeCollidedWith() { - return !this.removed; - } - - /** - * Sets a target for the client to interpolate towards over the next few ticks - */ - @OnlyIn(Dist.CLIENT) - @Override - public void setPositionAndRotationDirect(double x, double y, double z, float yaw, float pitch, int posRotationIncrements, boolean teleport) { - this.lerpX = x; - this.lerpY = y; - this.lerpZ = z; - this.lerpYaw = yaw; - this.lerpPitch = pitch; - this.lerpSteps = 10; - } - - /** - * Gets the horizontal facing direction of this Entity, adjusted to take specially-treated entity types into account. - */ - @Override - public Direction getAdjustedHorizontalFacing() { - return this.getHorizontalFacing().rotateY(); - } - - /** - * Update the boat's speed, based on momentum. - */ - private void updateMotion() { - double d1 = this.hasNoGravity() ? 0.0D : (double) -0.04F; - this.momentum = 0.05F; - this.momentum = this.boatGlide; - - if (this.getControllingPassenger() instanceof PlayerEntity) { - this.boatGlide /= 2.0F; - } - - Vector3d vector3d = this.getMotion(); - this.setMotion(vector3d.x * (double) this.momentum, vector3d.y + d1, vector3d.z * (double) this.momentum); - this.deltaRotation *= this.momentum; - } - - private void controlBoat() { - if (this.isBeingRidden()) { - float f = 0.0F; - if (this.leftInputDown) { - --this.deltaRotation; - } - - if (this.rightInputDown) { - ++this.deltaRotation; - } - - if (this.rightInputDown != this.leftInputDown && !this.forwardInputDown && !this.backInputDown) { - f += 0.005F; - } - - this.rotationYaw += this.deltaRotation; - if (this.forwardInputDown) { - f += 0.04F; - } - - if (this.backInputDown) { - f -= 0.005F; - } - - this.setMotion(this.getMotion().add( - MathHelper.sin(-this.rotationYaw * ((float) Math.PI / 180F)) * f, - 0.0D, MathHelper.cos(this.rotationYaw * ((float) Math.PI / 180F)) * f - )); - } - } - - @Override - public void updatePassenger(Entity passenger) { - if (this.isPassenger(passenger)) { - float f = 0.0F; - float f1 = (float) ((this.removed ? (double) 0.01F : this.getMountedYOffset()) + passenger.getYOffset()); - if (this.getPassengers().size() > 1) { - int i = this.getPassengers().indexOf(passenger); - if (i == 0) { - f = 0.2F; - } else { - f = -0.6F; - } - - if (passenger instanceof AnimalEntity) { - f = (float) ((double) f + 0.2D); - } - } - - Vector3d vector3d = (new Vector3d(f, 0.0D, 0.0D)).rotateYaw(-this.rotationYaw * ((float) Math.PI / 180F) - ((float) Math.PI / 2F)); - passenger.setPosition(this.getPosX() + vector3d.x, this.getPosY() + (double) f1, this.getPosZ() + vector3d.z); - passenger.rotationYaw += this.deltaRotation; - passenger.setRotationYawHead(passenger.getRotationYawHead() + this.deltaRotation); - this.applyYawToEntity(passenger); - if (passenger instanceof AnimalEntity && this.getPassengers().size() > 1) { - int j = passenger.getEntityId() % 2 == 0 ? 90 : 270; - passenger.setRenderYawOffset(((AnimalEntity) passenger).renderYawOffset + (float) j); - passenger.setRotationYawHead(passenger.getRotationYawHead() + (float) j); - } - - } - } - - /** - * Applies this boat's yaw to the given entity. Used to update the orientation of its passenger. - */ - protected void applyYawToEntity(Entity entityToUpdate) { - entityToUpdate.setRenderYawOffset(this.rotationYaw); - float f = MathHelper.wrapDegrees(entityToUpdate.rotationYaw - this.rotationYaw); - float f1 = MathHelper.clamp(f, -105.0F, 105.0F); - entityToUpdate.prevRotationYaw += f1 - f; - entityToUpdate.rotationYaw += f1 - f; - entityToUpdate.setRotationYawHead(entityToUpdate.rotationYaw); - } - - /** - * Applies this entity's orientation (pitch/yaw) to another entity. Used to update passenger orientation. - */ - @OnlyIn(Dist.CLIENT) - @Override - public void applyOrientationToEntity(Entity entityToUpdate) { - this.applyYawToEntity(entityToUpdate); - } - - @Override - public ActionResultType processInitialInteract(PlayerEntity player, Hand hand) { - if (player.isSecondaryUseActive()) { - return ActionResultType.PASS; - } - if (!this.world.isRemote) { - return player.startRiding(this) ? ActionResultType.CONSUME : ActionResultType.PASS; + } + } + this.setMotion(previousMotion); + this.move(MoverType.SELF, this.getMotion()); + this.doBlockCollisions(); + } + + private void tickLerp() { + if (this.canPassengerSteer()) { + this.lerpSteps = 0; + this.setPacketCoordinates(this.getPosX(), this.getPosY(), this.getPosZ()); + } + + if (this.lerpSteps > 0) { + double d0 = this.getPosX() + (this.lerpX - this.getPosX()) / (double) this.lerpSteps; + double d1 = this.getPosY() + (this.lerpY - this.getPosY()) / (double) this.lerpSteps; + double d2 = this.getPosZ() + (this.lerpZ - this.getPosZ()) / (double) this.lerpSteps; + double d3 = MathHelper.wrapDegrees(this.lerpYaw - (double) this.rotationYaw); + this.rotationYaw = (float) ((double) this.rotationYaw + d3 / (double) this.lerpSteps); + this.rotationPitch = + (float) + ((double) this.rotationPitch + + (this.lerpPitch - (double) this.rotationPitch) / (double) this.lerpSteps); + --this.lerpSteps; + this.setPosition(d0, d1, d2); + this.setRotation(this.rotationYaw, this.rotationPitch); + } + } + + @Override + protected void registerData() { + dataManager.register(STARTED, false); + dataManager.register(FUEL, 0.0F); + dataManager.register(QUATERNION, Quaternion.ONE); + } + + @Override + protected void readAdditional(@Nonnull CompoundNBT compound) { + this.storage = new BlockStorage(compound.getCompound("storage")); + } + + @Override + protected void writeAdditional(@Nonnull CompoundNBT compound) { + compound.put("storage", this.storage.toNBT()); + } + + public BlockStorage getStorage() { + return storage; + } + + @SuppressWarnings("deprecation") + @Override + public boolean attackEntityFrom(DamageSource source, float amount) { + if (this.isInvulnerableTo(source)) { + return false; + } + if (!(source.getTrueSource() instanceof PlayerEntity + && ((PlayerEntity) source.getTrueSource()).abilities.isCreativeMode) + && world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS) + && !this.removed) { + entityDropItem(Items.STICK); + } + if (!this.world.isRemote && !this.removed) { + remove(); + return true; + } + return false; + } + + /** + * Returns a boundingBox used to collide the entity with other entities and blocks. This enables + * the entity to be pushable on contact, like boats. + */ + @Nullable + @Override + public AxisAlignedBB getCollisionBox(Entity entityIn) { + return entityIn.canBePushed() ? entityIn.getBoundingBox() : null; + } + + /** + * Returns the solid collision bounding box for this entity. Used to make (e.g.) boats + * solid. Return null if this entity is not solid. + */ + @Nullable + @Override + public AxisAlignedBB getCollisionBoundingBox() { + return this.getBoundingBox(); + } + + /** Returns true if this entity should push and be pushed by other entities when colliding. */ + @Override + public boolean canBePushed() { + return true; + } + + /** Returns the Y offset from the entity's position for any entity riding this one. */ + // TODO SEATS + @Override + public double getMountedYOffset() { + return -0.1D; + } + + /** Applies a velocity to the entities, to push them away from eachother. */ + @Override + public void applyEntityCollision(Entity entityIn) { + if (entityIn instanceof BoatEntity) { + if (entityIn.getBoundingBox().minY < this.getBoundingBox().maxY) { + super.applyEntityCollision(entityIn); + } + } else if (entityIn.getBoundingBox().minY <= this.getBoundingBox().minY) { + super.applyEntityCollision(entityIn); + } + } + + /** Returns true if other Entities should be prevented from moving through this Entity. */ + @Override + public boolean canBeCollidedWith() { + return !this.removed; + } + + /** Sets a target for the client to interpolate towards over the next few ticks */ + @OnlyIn(Dist.CLIENT) + @Override + public void setPositionAndRotationDirect( + double x, + double y, + double z, + float yaw, + float pitch, + int posRotationIncrements, + boolean teleport) { + this.lerpX = x; + this.lerpY = y; + this.lerpZ = z; + this.lerpYaw = yaw; + this.lerpPitch = pitch; + this.lerpSteps = 10; + } + + /** + * Gets the horizontal facing direction of this Entity, adjusted to take specially-treated entity + * types into account. + */ + @Override + public Direction getAdjustedHorizontalFacing() { + return this.getHorizontalFacing().rotateY(); + } + + @Override + public void updatePassenger(Entity passenger) { + if (this.isPassenger(passenger)) { + float f = 0.0F; + float f1 = + (float) + ((this.removed ? (double) 0.01F : this.getMountedYOffset()) + passenger.getYOffset()); + if (this.getPassengers().size() > 1) { + int i = this.getPassengers().indexOf(passenger); + if (i == 0) { + f = 0.2F; } else { - return ActionResultType.SUCCESS; + f = -0.6F; } - } - - /** - * For vehicles, the first passenger is generally considered the controller and "drives" the vehicle. For example, - * Pigs, Horses, and Boats are generally "steered" by the controlling passenger. - */ - @Nullable - @Override - public Entity getControllingPassenger() { - List list = this.getPassengers(); - return list.isEmpty() ? null : list.get(0); - } - - @OnlyIn(Dist.CLIENT) - public void updateInputs(boolean p_184442_1_, boolean p_184442_2_, boolean p_184442_3_, boolean p_184442_4_) { - this.leftInputDown = p_184442_1_; - this.rightInputDown = p_184442_2_; - this.forwardInputDown = p_184442_3_; - this.backInputDown = p_184442_4_; - } - // Forge: Fix MC-119811 by instantly completing lerp on board - @Override - protected void addPassenger(Entity passenger) { - super.addPassenger(passenger); - if (this.canPassengerSteer() && this.lerpSteps > 0) { - this.lerpSteps = 0; - this.setPositionAndRotation(this.lerpX, this.lerpY, this.lerpZ, (float) this.lerpYaw, (float) this.lerpPitch); + if (passenger instanceof AnimalEntity) { + f = (float) ((double) f + 0.2D); } - } - - @Override - public Vector3d func_230268_c_(LivingEntity p_230268_1_) { - Vector3d vector3d = func_233559_a_(this.getWidth() * MathHelper.SQRT_2, p_230268_1_.getWidth(), this.rotationYaw); - double d0 = this.getPosX() + vector3d.x; - double d1 = this.getPosZ() + vector3d.z; - BlockPos blockpos = new BlockPos(d0, this.getBoundingBox().maxY, d1); - BlockPos blockpos1 = blockpos.down(); - if (!this.world.hasWater(blockpos1)) { - for (Pose pose : p_230268_1_.func_230297_ef_()) { - AxisAlignedBB axisalignedbb = p_230268_1_.func_233648_f_(pose); - double d2 = this.world.func_234936_m_(blockpos); - if (TransportationHelper.func_234630_a_(d2)) { - Vector3d vector3d1 = new Vector3d(d0, (double) blockpos.getY() + d2, d1); - if (TransportationHelper.func_234631_a_(this.world, p_230268_1_, axisalignedbb.offset(vector3d1))) { - p_230268_1_.setPose(pose); - return vector3d1; - } - } - - double d3 = this.world.func_234936_m_(blockpos1); - if (TransportationHelper.func_234630_a_(d3)) { - Vector3d vector3d2 = new Vector3d(d0, (double) blockpos1.getY() + d3, d1); - if (TransportationHelper.func_234631_a_(this.world, p_230268_1_, axisalignedbb.offset(vector3d2))) { - p_230268_1_.setPose(pose); - return vector3d2; - } - } - } + } + + Vector3d vector3d = + (new Vector3d(f, 0.0D, 0.0D)) + .rotateYaw(-this.rotationYaw * ((float) Math.PI / 180F) - ((float) Math.PI / 2F)); + passenger.setPosition( + this.getPosX() + vector3d.x, this.getPosY() + (double) f1, this.getPosZ() + vector3d.z); + this.applyYawToEntity(passenger); + if (passenger instanceof AnimalEntity && this.getPassengers().size() > 1) { + int j = passenger.getEntityId() % 2 == 0 ? 90 : 270; + passenger.setRenderYawOffset(((AnimalEntity) passenger).renderYawOffset + (float) j); + passenger.setRotationYawHead(passenger.getRotationYawHead() + (float) j); + } + } + } + + /** + * Applies this boat's yaw to the given entity. Used to update the orientation of its passenger. + */ + protected void applyYawToEntity(Entity entityToUpdate) { + entityToUpdate.setRenderYawOffset(this.rotationYaw); + float f = MathHelper.wrapDegrees(entityToUpdate.rotationYaw - this.rotationYaw); + float f1 = MathHelper.clamp(f, -105.0F, 105.0F); + entityToUpdate.prevRotationYaw += f1 - f; + entityToUpdate.rotationYaw += f1 - f; + entityToUpdate.setRotationYawHead(entityToUpdate.rotationYaw); + } + + /** + * Applies this entity's orientation (pitch/yaw) to another entity. Used to update passenger + * orientation. + */ + @OnlyIn(Dist.CLIENT) + @Override + public void applyOrientationToEntity(Entity entityToUpdate) { + this.applyYawToEntity(entityToUpdate); + } + + @Override + public ActionResultType processInitialInteract(PlayerEntity player, Hand hand) { + if (player.isSecondaryUseActive()) { + return ActionResultType.PASS; + } + if (!this.world.isRemote) { + return player.startRiding(this) ? ActionResultType.CONSUME : ActionResultType.PASS; + } else { + return ActionResultType.SUCCESS; + } + } + + /** + * For vehicles, the first passenger is generally considered the controller and "drives" the + * vehicle. For example, Pigs, Horses, and Boats are generally "steered" by the controlling + * passenger. + */ + @Nullable + @Override + public Entity getControllingPassenger() { + List list = this.getPassengers(); + return list.isEmpty() ? null : list.get(0); + } + + // Forge: Fix MC-119811 by instantly completing lerp on board + @Override + protected void addPassenger(Entity passenger) { + super.addPassenger(passenger); + if (this.canPassengerSteer() && this.lerpSteps > 0) { + this.lerpSteps = 0; + this.setPositionAndRotation( + this.lerpX, this.lerpY, this.lerpZ, (float) this.lerpYaw, (float) this.lerpPitch); + } + } + + @Override + public Vector3d func_230268_c_(LivingEntity p_230268_1_) { + Vector3d vector3d = + func_233559_a_( + this.getWidth() * MathHelper.SQRT_2, p_230268_1_.getWidth(), this.rotationYaw); + double d0 = this.getPosX() + vector3d.x; + double d1 = this.getPosZ() + vector3d.z; + BlockPos blockpos = new BlockPos(d0, this.getBoundingBox().maxY, d1); + BlockPos blockpos1 = blockpos.down(); + if (!this.world.hasWater(blockpos1)) { + for (Pose pose : p_230268_1_.func_230297_ef_()) { + AxisAlignedBB axisalignedbb = p_230268_1_.func_233648_f_(pose); + double d2 = this.world.func_234936_m_(blockpos); + if (TransportationHelper.func_234630_a_(d2)) { + Vector3d vector3d1 = new Vector3d(d0, (double) blockpos.getY() + d2, d1); + if (TransportationHelper.func_234631_a_( + this.world, p_230268_1_, axisalignedbb.offset(vector3d1))) { + p_230268_1_.setPose(pose); + return vector3d1; + } } - return super.func_230268_c_(p_230268_1_); - } - - @Override - protected boolean canBeRidden(Entity entityIn) { - return true; - } - - @Override - public boolean canBeRiddenInWater(Entity rider) { - return true; - } - - @Override - protected AxisAlignedBB getBoundingBox(Pose pose) { - AxisAlignedBB COLLISION_AABB = new AxisAlignedBB(-1, 0, -1, 1, 0.5, 1); - return COLLISION_AABB.offset(getPositionVec()); - } - - @Nonnull - @Override - public IPacket createSpawnPacket() { - return NetworkHooks.getEntitySpawningPacket(this); - } - - @Override - public void writeSpawnData(PacketBuffer dataStream) { - dataStream.writeCompoundTag(this.storage.toNBT()); - } - - @Override - public void readSpawnData(PacketBuffer dataStream) { - MSP.LOGGER.debug("spawn data"); - this.storage = new BlockStorage(dataStream.readCompoundTag()); - MSP.LOGGER.debug("number :" + this.storage.numberOfBlocks); - } - - /** - * @return The player controlling the rocket - */ - public PlayerEntity getControllingPlayer() { - Entity entity = getControllingPassenger(); - if (entity instanceof PlayerEntity) { - return (PlayerEntity) entity; + double d3 = this.world.func_234936_m_(blockpos1); + if (TransportationHelper.func_234630_a_(d3)) { + Vector3d vector3d2 = new Vector3d(d0, (double) blockpos1.getY() + d3, d1); + if (TransportationHelper.func_234631_a_( + this.world, p_230268_1_, axisalignedbb.offset(vector3d2))) { + p_230268_1_.setPose(pose); + return vector3d2; + } } - return null; - } + } + } + + return super.func_230268_c_(p_230268_1_); + } + + @Override + protected boolean canBeRidden(Entity entityIn) { + return true; + } + + @Override + public boolean canBeRiddenInWater(Entity rider) { + return true; + } + + @Override + protected AxisAlignedBB getBoundingBox(Pose pose) { + // if(storage != null) { + return AABB; + // return new AxisAlignedBB(0,0,0,1,1,1); + + // AxisAlignedBB COLLISION_AABB = new AxisAlignedBB(-1, 0, -1, 1, 0.5, 1); + // return COLLISION_AABB.offset(getPositionVec()); + } + + @Nonnull + @Override + public IPacket createSpawnPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } + + @Override + public void writeSpawnData(PacketBuffer dataStream) { + dataStream.writeCompoundTag(this.storage.toNBT()); + } + + @Override + public void readSpawnData(PacketBuffer dataStream) { + CompoundNBT compound = dataStream.readCompoundTag(); + if (compound != null) { + this.storage = new BlockStorage(compound); + } else { + throw new IllegalArgumentException("Data Stream does not contain the CompoundNBT"); + } + } + + public void spawnParticle( + String particle, + World world, + double x, + double y, + double z, + double motionX, + double motionY, + double motionZ) { + // WTF how is == working? Should be .equals + if (particle.equals("rocketFlame")) { + // RocketFx fx = new RocketFx(world, x, y, z, motionX, motionY, motionZ); + world.addParticle(ParticleTypes.SMOKE, x, y, z, motionX, motionY, motionZ); + } else if (particle.equals(("rocketSmoke"))) { + // TrailFx fx = new TrailFx(world, x, y, z, motionX, motionY, motionZ); + world.addParticle(ParticleTypes.SMOKE, x, y, z, motionX, motionY, motionZ); + } + } } diff --git a/src/main/java/io/github/MinecraftSpaceProgram/MSP/entity/RocketEntityType.java b/src/main/java/io/github/MinecraftSpaceProgram/MSP/entity/RocketEntityType.java index 947ad58..36bedf3 100644 --- a/src/main/java/io/github/MinecraftSpaceProgram/MSP/entity/RocketEntityType.java +++ b/src/main/java/io/github/MinecraftSpaceProgram/MSP/entity/RocketEntityType.java @@ -18,7 +18,7 @@ public RocketEntityType(ResourceLocation texture, boolean immuneToFire) { immuneToFire, true, ImmutableSet.of(), - EntitySize.flexible(2.0f, 0.5f), + EntitySize.flexible(1.0F, 1.0f), 5, 3); this.texture = texture; diff --git a/src/main/java/io/github/MinecraftSpaceProgram/MSP/init/MSPDataSerializers.java b/src/main/java/io/github/MinecraftSpaceProgram/MSP/init/MSPDataSerializers.java new file mode 100644 index 0000000..6fc676e --- /dev/null +++ b/src/main/java/io/github/MinecraftSpaceProgram/MSP/init/MSPDataSerializers.java @@ -0,0 +1,74 @@ +package io.github.MinecraftSpaceProgram.MSP.init; + +import io.github.MinecraftSpaceProgram.MSP.MSP; +import io.github.MinecraftSpaceProgram.MSP.util.BlockStorage; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.datasync.IDataSerializer; +import net.minecraft.util.math.vector.Quaternion; +import net.minecraftforge.fml.RegistryObject; +import net.minecraftforge.registries.DataSerializerEntry; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; + +import javax.annotation.ParametersAreNonnullByDefault; + +@SuppressWarnings("unused") +@ParametersAreNonnullByDefault +public class MSPDataSerializers { + public static final DeferredRegister DATA_SERIALIZERS = DeferredRegister.create(ForgeRegistries.DATA_SERIALIZERS, MSP.MOD_ID); + + public static final IDataSerializer QUATERNION_SERIALIZER = new IDataSerializer() { + + @Override + public void write(PacketBuffer buf, Quaternion q) { + buf.writeFloat(q.getX()); + buf.writeFloat(q.getY()); + buf.writeFloat(q.getZ()); + buf.writeFloat(q.getW()); + } + + @Override + public Quaternion read(PacketBuffer buf) { + try { + return new Quaternion(buf.readFloat(), buf.readFloat(), buf.readFloat(), buf.readFloat()); + } catch (IndexOutOfBoundsException e) { + // This function would throw anyway, might as well wrap the error with more relevant info + throw new RuntimeException("packet buffer does not contain enough data to construct plane's Quaternion", e); + } + } + + @Override + public Quaternion copyValue(Quaternion q) + { + return new Quaternion(q); + } + }; + + public static final IDataSerializer STORAGE_SERIALIZER = new IDataSerializer() { + + @Override + public void write(PacketBuffer buf, BlockStorage storage) { + buf.writeCompoundTag(storage.toNBT()); + } + + @Override + public BlockStorage read(PacketBuffer buf) { + CompoundNBT compound = buf.readCompoundTag(); + if( compound != null){ + return new BlockStorage(compound); + } else { + throw new IllegalArgumentException("buffer does not contain a compoundNBT"); + } + } + + @Override + public BlockStorage copyValue(BlockStorage storage) + { + return new BlockStorage(storage); + } + }; + + public static final RegistryObject QUAT_SERIALIZER = DATA_SERIALIZERS.register("quaternion", () -> new DataSerializerEntry(QUATERNION_SERIALIZER)); + public static final RegistryObject STORE_SERIALIZER = DATA_SERIALIZERS.register("storage", () -> new DataSerializerEntry(STORAGE_SERIALIZER)); +} \ No newline at end of file diff --git a/src/main/java/io/github/MinecraftSpaceProgram/MSP/physics/orbital/PhysicsUtil.java b/src/main/java/io/github/MinecraftSpaceProgram/MSP/physics/orbital/PhysicsUtil.java index fdb52eb..5505139 100644 --- a/src/main/java/io/github/MinecraftSpaceProgram/MSP/physics/orbital/PhysicsUtil.java +++ b/src/main/java/io/github/MinecraftSpaceProgram/MSP/physics/orbital/PhysicsUtil.java @@ -13,6 +13,11 @@ public final class PhysicsUtil { */ public static final double G = 6.674 * E(-11); + /** + * the length of a tick in s + */ + public static final double TICK_LENGTH = 0.05D; + /** * The Astronomical Unit */ diff --git a/src/main/java/io/github/MinecraftSpaceProgram/MSP/rocket/Rocket.java b/src/main/java/io/github/MinecraftSpaceProgram/MSP/rocket/Rocket.java index 981eb46..cdf06f9 100644 --- a/src/main/java/io/github/MinecraftSpaceProgram/MSP/rocket/Rocket.java +++ b/src/main/java/io/github/MinecraftSpaceProgram/MSP/rocket/Rocket.java @@ -153,7 +153,6 @@ private boolean enforceEnginesFacingOutwards() { case WEST: if (rocketBlocksPos.contains(blockPos.add(1,0,0))) return false; default: - throw new IllegalArgumentException(); } } else { diff --git a/src/main/java/io/github/MinecraftSpaceProgram/MSP/util/BlockStorage.java b/src/main/java/io/github/MinecraftSpaceProgram/MSP/util/BlockStorage.java index 975efb4..e0584a3 100644 --- a/src/main/java/io/github/MinecraftSpaceProgram/MSP/util/BlockStorage.java +++ b/src/main/java/io/github/MinecraftSpaceProgram/MSP/util/BlockStorage.java @@ -75,6 +75,18 @@ public BlockStorage(BlockState[][][] blockStates, int x, int y, int z, int sizeX this.numberOfBlocks = numberOfBlocks; } + public BlockStorage(BlockStorage blockStorage) { + this( + blockStorage.blockStates, + blockStorage.x, + blockStorage.y, + blockStorage.z, + blockStorage.sizeX, + blockStorage.sizeY, + blockStorage.sizeZ, + blockStorage.numberOfBlocks); + } + @Nullable public BlockState getBlockState(BlockPos pos) { if (pos.getX() < 0 || pos.getX() > sizeX || pos.getY() < 0 || pos.getY() > sizeY || pos.getZ() < 0 || pos.getZ() > sizeZ) @@ -86,6 +98,7 @@ public BlockState getBlockState(BlockPos pos) { // return tileEntities; //} + public CompoundNBT toNBT() { CompoundNBT compoundnbt = new CompoundNBT(); compoundnbt.putInt("x", this.x); @@ -101,7 +114,7 @@ public CompoundNBT toNBT() { for (int z = 0; z < this.sizeZ; z++) { if (this.blockStates[x][y][z] != null) { compoundnbt.put("BlockState[" + x + "][" + y + "][" + z + "]", NBTUtil.writeBlockState(this.blockStates[x][y][z])); - MSP.LOGGER.debug("key: " + (int)compoundnbt.getTagId("BlockState[" + x + "][" + y + "][" + z + "]")); + MSP.LOGGER.debug("key: " + (int) compoundnbt.getTagId("BlockState[" + x + "][" + y + "][" + z + "]")); } } } @@ -125,9 +138,9 @@ public BlockStorage(CompoundNBT compoundNBT) { for (int x = 0; x < this.sizeX; x++) { for (int y = 0; y < this.sizeY; y++) { for (int z = 0; z < this.sizeZ; z++) { - if(compoundNBT.contains("BlockState[" + x + "][" + y + "][" + z + "]", 10)){ + if (compoundNBT.contains("BlockState[" + x + "][" + y + "][" + z + "]", 10)) { this.blockStates[x][y][z] = NBTUtil.readBlockState(compoundNBT.getCompound("BlockState[" + x + "][" + y + "][" + z + "]")); - numberOfBlocksActual ++; + numberOfBlocksActual++; } else { this.blockStates[x][y][z] = null; } @@ -135,7 +148,7 @@ public BlockStorage(CompoundNBT compoundNBT) { } } - if (numberOfBlocksActual != this.numberOfBlocks){ + if (numberOfBlocksActual != this.numberOfBlocks) { MSP.LOGGER.error("----- NBT TRANSLATION FAILED -----"); } }