diff --git a/gradle.properties b/gradle.properties index 5d6ed258b..648b66d9a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ org.gradle.daemon=false # mod version info mod_version=0.3 minecraft_version=1.15.2 -forge_version=31.2.3 +forge_version=31.2.21 # dependency versions registrate_version=0.0.3.17 diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java index 3291cc07b..235858024 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java @@ -1,10 +1,18 @@ package com.simibubi.create.content.contraptions.components.structureMovement; -import java.util.HashMap; -import java.util.Map; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.ExecutionException; import org.apache.commons.lang3.mutable.MutableBoolean; +import com.google.common.base.Predicates; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.actors.BlockBreakingMovementBehaviour; import com.simibubi.create.foundation.collision.Matrix3d; @@ -14,11 +22,10 @@ import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; import net.minecraft.block.CocoaBlock; -import net.minecraft.block.material.PushReaction; import net.minecraft.client.Minecraft; +import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; -import net.minecraft.entity.IProjectile; import net.minecraft.entity.MoverType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; @@ -34,21 +41,72 @@ import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.event.TickEvent.ClientTickEvent; +import net.minecraftforge.event.TickEvent.Phase; +import net.minecraftforge.event.TickEvent.WorldTickEvent; +import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +@EventBusSubscriber public class ContraptionCollider { - static Map renderedBBs = new HashMap<>(); public static boolean wasClientPlayerGrounded; + public static Cache>> activeContraptions = CacheBuilder.newBuilder() + .expireAfterAccess(20, SECONDS) + .build(); + + @SubscribeEvent + public static void addSpawnedContraptionsToCollisionList(EntityJoinWorldEvent event) { + Entity entity = event.getEntity(); + if (!(entity instanceof ContraptionEntity)) + return; + try { + List> list = activeContraptions.get(event.getWorld(), ArrayList::new); + ContraptionEntity contraption = (ContraptionEntity) entity; + list.add(new WeakReference<>(contraption)); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + + @SubscribeEvent + @OnlyIn(Dist.CLIENT) + public static void playerCollisionHappensOnClientTick(ClientTickEvent event) { + if (event.phase == Phase.START) + return; + ClientWorld world = Minecraft.getInstance().world; + if (world == null) + return; + runCollisions(world); + } + + @SubscribeEvent + public static void entityCollisionHappensPreWorldTick(WorldTickEvent event) { + if (event.phase == Phase.START) + return; + World world = event.world; + runCollisions(world); + } + + private static void runCollisions(World world) { + List> list = activeContraptions.getIfPresent(world); + if (list == null) + return; + for (Iterator> iterator = list.iterator(); iterator.hasNext();) { + WeakReference weakReference = iterator.next(); + ContraptionEntity contraptionEntity = weakReference.get(); + if (contraptionEntity == null || !contraptionEntity.isAlive()) { + iterator.remove(); + continue; + } + collideEntities(contraptionEntity); + } + } public static void collideEntities(ContraptionEntity contraptionEntity) { - if (Contraption.isFrozen()) - return; - if (!contraptionEntity.collisionEnabled()) - return; - World world = contraptionEntity.getEntityWorld(); -// Vec3d contraptionMotion = contraptionEntity.getMotion(); Contraption contraption = contraptionEntity.getContraption(); AxisAlignedBB bounds = contraptionEntity.getBoundingBox(); Vec3d contraptionPosition = contraptionEntity.getPositionVec(); @@ -61,7 +119,7 @@ public class ContraptionCollider { return; for (Entity entity : world.getEntitiesWithinAABB((EntityType) null, bounds.grow(1), - e -> canBeCollidedWith(e))) { + contraptionEntity::canCollideWith)) { if (entity instanceof PlayerEntity && !world.isRemote) return; @@ -70,7 +128,7 @@ public class ContraptionCollider { Vec3d centerY = new Vec3d(0, entity.getBoundingBox() .getYSize() / 2, 0); Vec3d position = entityPosition.subtract(contraptionPosition) - .subtract(centerOfBlock) + .subtract(contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0)) .add(centerY); position = VecHelper.rotate(position, -contraptionRotation.z, -contraptionRotation.y, -contraptionRotation.x); @@ -107,7 +165,7 @@ public class ContraptionCollider { obb.setCenter(obb.getCenter() .add(intersect)); - entity.move(MoverType.PLAYER, intersect); + entity.move(MoverType.PISTON, intersect); Vec3d entityMotion = entity.getMotion(); if (entityMotion.getX() > 0 == intersect.getX() < 0) @@ -134,49 +192,10 @@ public class ContraptionCollider { if (entity instanceof ServerPlayerEntity) ((ServerPlayerEntity) entity).connection.floatingTickCount = 0; }); - -// Vec3d positionOffset = contraptionPosition.scale(-1); -// AxisAlignedBB entityBB = entity.getBoundingBox() -// .offset(positionOffset) -// .grow(1.0E-7D); -// Vec3d entityMotion = entity.getMotion(); -// Vec3d relativeMotion = entityMotion.subtract(contraptionMotion); -// Vec3d allowedMovement = Entity.getAllowedMovement(relativeMotion, entityBB, world, -// ISelectionContext.forEntity(entity), potentialHits); -// potentialHits.createStream() -// .forEach(voxelShape -> pushEntityOutOfShape(entity, voxelShape, positionOffset, contraptionMotion)); -// -// -// if (allowedMovement.equals(relativeMotion)) -// continue; -// -// if (allowedMovement.y != relativeMotion.y) { -// entity.handleFallDamage(entity.fallDistance, 1); -// entity.fallDistance = 0; -// entity.onGround = true; -// DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> checkForClientPlayerCollision(entity)); -// } -// -// if (entity instanceof ServerPlayerEntity) -// ((ServerPlayerEntity) entity).connection.floatingTickCount = 0; -// if (entity instanceof PlayerEntity && !world.isRemote) -// return; -// -// entity.setMotion(allowedMovement.add(contraptionMotion)); } } - public static boolean canBeCollidedWith(Entity e) { - if (e instanceof PlayerEntity && e.isSpectator()) - return false; - if (e.noClip) - return false; - if (e instanceof IProjectile) - return false; - return e.getPushReaction() == PushReaction.NORMAL; - } - @OnlyIn(Dist.CLIENT) private static void checkForClientPlayerCollision(Entity entity) { if (entity != Minecraft.getInstance().player) @@ -258,7 +277,8 @@ public class ContraptionCollider { BlockPos pos = contraption.blocks.get(p).pos; VoxelShape collisionShape = blockState.getCollisionShape(world, p); return collisionShape.withOffset(pos.getX(), pos.getY(), pos.getZ()); - })); + }) + .filter(Predicates.not(VoxelShape::isEmpty))); return potentialHits; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntity.java index 731e3cd51..db84d00ca 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntity.java @@ -12,6 +12,7 @@ import org.apache.commons.lang3.tuple.MutablePair; import com.google.common.collect.ImmutableSet; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingContraption; +import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption; import com.simibubi.create.foundation.item.ItemHelper; @@ -24,8 +25,11 @@ import net.minecraft.block.material.PushReaction; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; +import net.minecraft.entity.IProjectile; import net.minecraft.entity.item.BoatEntity; +import net.minecraft.entity.item.HangingEntity; import net.minecraft.entity.item.minecart.FurnaceMinecartEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.item.crafting.Ingredient; @@ -103,7 +107,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD } public static ContraptionEntity createMounted(World world, Contraption contraption, float initialAngle, - Direction facing) { + Direction facing) { ContraptionEntity entity = createMounted(world, contraption, initialAngle); entity.forcedAngle = facing.getHorizontalAngle(); entity.forceYaw(entity.forcedAngle); @@ -170,7 +174,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD } public void collisionTick() { - ContraptionCollider.collideEntities(this); +// ContraptionCollider.collideEntities(this); } public void tickAsPassenger(Entity e) { @@ -233,14 +237,17 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD int i = MathHelper.floor(furnaceCart.getX()); int j = MathHelper.floor(furnaceCart.getY()); int k = MathHelper.floor(furnaceCart.getZ()); - if (furnaceCart.world.getBlockState(new BlockPos(i, j - 1, k)).isIn(BlockTags.RAILS)) + if (furnaceCart.world.getBlockState(new BlockPos(i, j - 1, k)) + .isIn(BlockTags.RAILS)) --j; BlockPos blockpos = new BlockPos(i, j, k); BlockState blockstate = this.world.getBlockState(blockpos); if (furnaceCart.canUseRail() && blockstate.isIn(BlockTags.RAILS)) if (fuel > 1) - riding.setMotion(riding.getMotion().normalize().scale(1)); + riding.setMotion(riding.getMotion() + .normalize() + .scale(1)); if (fuel < 5 && contraption != null) { ItemStack coal = ItemHelper.extract(contraption.inventory, FUEL_ITEMS, 1, false); if (!coal.isEmpty()) @@ -277,7 +284,8 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD Vec3d actorPosition = new Vec3d(blockInfo.pos); actorPosition = actorPosition.add(actor.getActiveAreaOffset(context)); actorPosition = VecHelper.rotate(actorPosition, angleRoll, angleYaw, anglePitch); - actorPosition = actorPosition.add(rotationOffset).add(getAnchorVec()); + actorPosition = actorPosition.add(rotationOffset) + .add(getAnchorVec()); boolean newPosVisited = false; BlockPos gridPosition = new BlockPos(actorPosition); @@ -290,7 +298,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD relativeMotion = VecHelper.rotate(relativeMotion, -angleRoll, -angleYaw, -anglePitch); context.relativeMotion = relativeMotion; newPosVisited = !new BlockPos(previousPosition).equals(gridPosition) - || context.relativeMotion.length() > 0 && context.firstMovement; + || context.relativeMotion.length() > 0 && context.firstMovement; } if (getContraption() instanceof BearingContraption) { @@ -298,10 +306,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD Direction facing = bc.getFacing(); Vec3d activeAreaOffset = actor.getActiveAreaOffset(context); if (activeAreaOffset.mul(VecHelper.planeByNormal(new Vec3d(facing.getDirectionVec()))) - .equals(Vec3d.ZERO)) { + .equals(Vec3d.ZERO)) { if (VecHelper.onSameAxis(blockInfo.pos, BlockPos.ZERO, facing.getAxis())) { - context.motion = new Vec3d(facing.getDirectionVec()).scale( - facing.getAxis().getCoordinate(roll - prevRoll, yaw - prevYaw, pitch - prevPitch)); + context.motion = new Vec3d(facing.getDirectionVec()).scale(facing.getAxis() + .getCoordinate(roll - prevRoll, yaw - prevYaw, pitch - prevPitch)); context.relativeMotion = context.motion; int timer = context.data.getInt("StationaryTimer"); if (timer > 0) { @@ -333,7 +341,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD if (getController() != null) getController().onStall(); AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), - new ContraptionStallPacket(getEntityId(), getX(), getY(), getZ(), yaw, pitch, roll)); + new ContraptionStallPacket(getEntityId(), getX(), getY(), getZ(), yaw, pitch, roll)); } dataManager.set(STALLED, contraption.stalled); } else { @@ -353,7 +361,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD public void rotateTo(double roll, double yaw, double pitch) { rotate(getShortestAngleDiff(this.roll, roll), getShortestAngleDiff(this.yaw, yaw), - getShortestAngleDiff(this.pitch, pitch)); + getShortestAngleDiff(this.pitch, pitch)); } @Override @@ -397,7 +405,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD public float getYaw(float partialTicks) { return (getRidingEntity() == null ? 1 : -1) - * (partialTicks == 1.0F ? yaw : angleLerp(partialTicks, prevYaw, yaw)) + initialAngle; + * (partialTicks == 1.0F ? yaw : angleLerp(partialTicks, prevYaw, yaw)) + initialAngle; } public float getPitch(float partialTicks) { @@ -463,7 +471,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD compound.put("Contraption", contraption.writeNBT()); if (!stationary && motionBeforeStall != null) compound.put("CachedMotion", - newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z)); + newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z)); if (controllerPos != null) compound.put("Controller", NBTUtil.writeBlockPos(controllerPos)); if (forcedAngle != -1) @@ -504,8 +512,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD } @Override - protected void doWaterSplashEffect() { - } + protected void doWaterSplashEffect() {} public void preventMovedEntitiesFromGettingStuck() { Vec3d stuckTest = new Vec3d(0, -2, 0); @@ -514,31 +521,33 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD e.onGround = true; Vec3d vec = stuckTest; - AxisAlignedBB axisalignedbb = e.getBoundingBox().offset(0, 2, 0); + AxisAlignedBB axisalignedbb = e.getBoundingBox() + .offset(0, 2, 0); ISelectionContext iselectioncontext = ISelectionContext.forEntity(this); - VoxelShape voxelshape = e.world.getWorldBorder().getShape(); + VoxelShape voxelshape = e.world.getWorldBorder() + .getShape(); Stream stream = VoxelShapes.compare(voxelshape, VoxelShapes.create(axisalignedbb.shrink(1.0E-7D)), IBooleanFunction.AND) - ? Stream.empty() - : Stream.of(voxelshape); + ? Stream.empty() + : Stream.of(voxelshape); Stream stream1 = this.world.getEmptyCollisionShapes(e, axisalignedbb.expand(vec), ImmutableSet.of()); ReuseableStream reuseablestream = new ReuseableStream<>(Stream.concat(stream1, stream)); Vec3d vec3d = vec.lengthSquared() == 0.0D ? vec - : collideBoundingBoxHeuristically(this, vec, axisalignedbb, e.world, iselectioncontext, - reuseablestream); + : collideBoundingBoxHeuristically(this, vec, axisalignedbb, e.world, iselectioncontext, + reuseablestream); boolean flag = vec.x != vec3d.x; boolean flag1 = vec.y != vec3d.y; boolean flag2 = vec.z != vec3d.z; boolean flag3 = e.onGround || flag1 && vec.y < 0.0D; if (this.stepHeight > 0.0F && flag3 && (flag || flag2)) { Vec3d vec3d1 = collideBoundingBoxHeuristically(e, new Vec3d(vec.x, (double) e.stepHeight, vec.z), - axisalignedbb, e.world, iselectioncontext, reuseablestream); + axisalignedbb, e.world, iselectioncontext, reuseablestream); Vec3d vec3d2 = collideBoundingBoxHeuristically(e, new Vec3d(0.0D, (double) e.stepHeight, 0.0D), - axisalignedbb.expand(vec.x, 0.0D, vec.z), e.world, iselectioncontext, reuseablestream); + axisalignedbb.expand(vec.x, 0.0D, vec.z), e.world, iselectioncontext, reuseablestream); if (vec3d2.y < (double) e.stepHeight) { Vec3d vec3d3 = collideBoundingBoxHeuristically(e, new Vec3d(vec.x, 0.0D, vec.z), - axisalignedbb.offset(vec3d2), e.world, iselectioncontext, reuseablestream).add(vec3d2); + axisalignedbb.offset(vec3d2), e.world, iselectioncontext, reuseablestream).add(vec3d2); if (horizontalMag(vec3d3) > horizontalMag(vec3d1)) { vec3d1 = vec3d3; } @@ -546,7 +555,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD if (horizontalMag(vec3d1) > horizontalMag(vec3d)) { vec3d = vec3d1.add(collideBoundingBoxHeuristically(e, new Vec3d(0.0D, -vec3d1.y + vec.y, 0.0D), - axisalignedbb.offset(vec3d1), e.world, iselectioncontext, reuseablestream)); + axisalignedbb.offset(vec3d1), e.world, iselectioncontext, reuseablestream)); } } @@ -568,7 +577,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD @OnlyIn(Dist.CLIENT) @Override public void setPositionAndRotationDirect(double x, double y, double z, float yaw, float pitch, - int posRotationIncrements, boolean teleport) { + int posRotationIncrements, boolean teleport) { // Stationary Anchors are responsible for keeping position and motion in sync // themselves. if (stationary) @@ -592,8 +601,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD @Override // Make sure nothing can move contraptions out of the way - public void setMotion(Vec3d motionIn) { - } + public void setMotion(Vec3d motionIn) {} @Override public void setPositionAndUpdate(double x, double y, double z) { @@ -623,9 +631,31 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD public float getInitialAngle() { return initialAngle; } - + public Vec3d getRotationVec() { - return new Vec3d(pitch, yaw, roll); + return new Vec3d(getPitch(1), getYaw(1), getRoll(1)); + } + + public boolean canCollideWith(Entity e) { + if (e instanceof PlayerEntity && e.isSpectator()) + return false; + if (e.noClip) + return false; + if (e instanceof HangingEntity) + return false; + if (e instanceof SuperGlueEntity) + return false; + if (e instanceof IProjectile) + return false; + + Entity riding = this.getRidingEntity(); + while (riding != null) { + if (riding == e) + return false; + riding = riding.getRidingEntity(); + } + + return e.getPushReaction() == PushReaction.NORMAL; } }