diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index b1416a530..975a01f43 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -3,6 +3,7 @@ package com.simibubi.create; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import com.simibubi.create.modules.contraptions.receivers.constructs.MovingConstructHandler; import com.simibubi.create.modules.logistics.FrequencyHandler; import com.simibubi.create.modules.logistics.InWorldItemProcessingHandler; import com.simibubi.create.modules.schematics.ServerSchematicLoader; @@ -31,12 +32,14 @@ public class Create { public static ServerSchematicLoader schematicReceiver; public static FrequencyHandler frequencyHandler; public static InWorldItemProcessingHandler itemProcessingHandler; + public static MovingConstructHandler constructHandler; @SubscribeEvent public static void init(final FMLCommonSetupEvent event) { schematicReceiver = new ServerSchematicLoader(); itemProcessingHandler = new InWorldItemProcessingHandler(); frequencyHandler = new FrequencyHandler(); + constructHandler = new MovingConstructHandler(); AllPackets.registerPackets(); } diff --git a/src/main/java/com/simibubi/create/Events.java b/src/main/java/com/simibubi/create/Events.java index a6d993c9f..324cb5170 100644 --- a/src/main/java/com/simibubi/create/Events.java +++ b/src/main/java/com/simibubi/create/Events.java @@ -29,6 +29,7 @@ public class Events { IWorld world = event.getWorld(); Create.itemProcessingHandler.onLoadWorld(world); Create.frequencyHandler.onLoadWorld(world); + Create.constructHandler.onLoadWorld(world); } @SubscribeEvent @@ -36,7 +37,7 @@ public class Events { IWorld world = event.getWorld(); Create.itemProcessingHandler.onUnloadWorld(world); Create.frequencyHandler.onUnloadWorld(world); - + Create.constructHandler.onUnloadWorld(world); } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/ConstructEntityHelper.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/ConstructEntityHelper.java deleted file mode 100644 index 321fc86d5..000000000 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/ConstructEntityHelper.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.simibubi.create.modules.contraptions.receivers.constructs; - -import java.util.LinkedList; -import java.util.List; -import java.util.stream.Stream; - -import com.mojang.blaze3d.platform.GlStateManager; -import com.simibubi.create.foundation.utility.TessellatorHelper; - -import net.minecraft.block.material.PushReaction; -import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.util.Direction; -import net.minecraft.util.ReuseableStream; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.world.World; -import net.minecraftforge.client.event.RenderWorldLastEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; - -@EventBusSubscriber -public class ConstructEntityHelper { - - static List renderedBBs = new LinkedList<>(); - - public static void moveEntities(MechanicalPistonTileEntity te, float movementSpeed, Direction movementDirection, - float newOffset) { - World world = te.getWorld(); - Vec3d movementVec = new Vec3d(te.getBlockState().get(BlockStateProperties.FACING).getDirectionVec()); - Construct construct = te.movingConstruct; - - if (world.isRemote) { - renderedBBs.clear(); - if (construct.collisionBoxFront != null) - renderedBBs.add(construct.collisionBoxFront.offset(te.getConstructOffset(0))); - if (construct.collisionBoxBack != null) - renderedBBs.add(construct.collisionBoxBack.offset(te.getConstructOffset(0))); - - } - - if (construct.getCollisionBoxFront() != null) { - AxisAlignedBB constructBB = construct.getCollisionBoxFront().offset(te.getConstructOffset(0)).grow(.5f); - - if (world.isRemote) { - renderedBBs.add(constructBB); - } - - for (Entity entity : world.getEntitiesWithinAABB((EntityType) null, constructBB, - e -> e.getPushReaction() == PushReaction.NORMAL)) { - - AxisAlignedBB entityBB = entity.getBoundingBox().offset(movementVec.scale(-1 * newOffset)).grow(.5f); - BlockPos min = new BlockPos(entityBB.minX, entityBB.minY, entityBB.minZ);// .add(-1, -1, -1); - BlockPos max = new BlockPos(entityBB.maxX, entityBB.maxY, entityBB.maxZ);// .add(1, 1, 1); - - Stream hits = BlockPos.getAllInBox(min, max).filter(construct.blocks::containsKey) - .map(pos -> { - Vec3d vec = new Vec3d(pos).add(te.getConstructOffset(0)); - return construct.blocks.get(pos).state.getShape(world, new BlockPos(vec)).withOffset(vec.x, - vec.y, vec.z); - }); - ReuseableStream potentialHits = new ReuseableStream<>(hits); - - // TODO: debug output - if (!world.isRemote) { - if (entity instanceof PlayerEntity) - ((PlayerEntity) entity).sendStatusMessage( - new StringTextComponent("Potential Hits: " + potentialHits.createStream().count()), - true); - } - ///////////////// - - if (world.isRemote) { - for (Object shape : potentialHits.createStream().toArray()) - renderedBBs.add(((VoxelShape) shape).getBoundingBox()); - renderedBBs - .add(entity.getBoundingBox().offset(movementVec.scale(Math.signum(movementSpeed) * -.2f))); - } - - Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(-movementSpeed) - .add(entity.getMotion()); - Vec3d allowedMovement = Entity.getAllowedMovement(movement, - entity.getBoundingBox().offset(movementVec.scale(Math.signum(movementSpeed) * -.2f)), world, - ISelectionContext.forEntity(entity), potentialHits); - - if (!allowedMovement.equals(movement)) { - entity.setMotion(allowedMovement.subtract(movement.subtract(entity.getMotion()))); - } - - } - } - } - - @SubscribeEvent - public static void onRenderWorld(RenderWorldLastEvent event) { -// for (AxisAlignedBB bb : renderedBBs) { -// TessellatorHelper.prepareForDrawing(); -// GlStateManager.disableTexture(); -// GlStateManager.lineWidth(3); -// WorldRenderer.drawSelectionBoundingBox(bb.grow(1 / 256f), .5f, 1, .5f, 1); -// GlStateManager.lineWidth(1); -// GlStateManager.enableTexture(); -// TessellatorHelper.cleanUpAfterDrawing(); -// } - } - -} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonTileEntity.java index c07845798..748632ada 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonTileEntity.java @@ -1,12 +1,11 @@ package com.simibubi.create.modules.contraptions.receivers.constructs; -import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; -import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTileEntities; +import com.simibubi.create.Create; import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonBlock.PistonState; @@ -25,8 +24,6 @@ import net.minecraft.world.gen.feature.template.Template.BlockInfo; public class MechanicalPistonTileEntity extends KineticTileEntity implements ITickableTileEntity { - protected static List movingPistons = new ArrayList<>(); - protected Construct movingConstruct; protected float offset; protected boolean running; @@ -107,7 +104,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi // Run running = true; offset = movingConstruct.initialExtensionProgress; - movingPistons.add(this); + if (!world.isRemote) + Create.constructHandler.add(this); sendData(); getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66); @@ -117,7 +115,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi continue; getWorld().setBlockState(startPos, Blocks.AIR.getDefaultState(), 67); } - + onBlockVisited(offset); } @@ -146,7 +144,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi } running = false; - movingPistons.remove(this); + if (!world.isRemote) + Create.constructHandler.remove(this); movingConstruct = null; sendData(); } @@ -171,7 +170,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi Direction movementDirection = getBlockState().get(BlockStateProperties.FACING); float newOffset = offset + movementSpeed; - ConstructEntityHelper.moveEntities(this, movementSpeed, movementDirection, newOffset); + MovingConstructHandler.moveEntities(this, movementSpeed, movementDirection, newOffset); if (world.isRemote) { offset = newOffset; @@ -208,7 +207,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi // Other moving Pistons int maxPossibleRange = Construct.MAX_EXTENSIONS + Construct.MAX_CHAINED_BLOCKS + Construct.MAX_CHAINED_CHASSIS; - Iterator iterator = movingPistons.iterator(); + Iterator iterator = Create.constructHandler.getOtherMovingPistonsInWorld(this) + .iterator(); while (iterator.hasNext()) { MechanicalPistonTileEntity otherPiston = iterator.next(); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MovingConstructHandler.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MovingConstructHandler.java new file mode 100644 index 000000000..107874820 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MovingConstructHandler.java @@ -0,0 +1,179 @@ +package com.simibubi.create.modules.contraptions.receivers.constructs; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import com.simibubi.create.Create; + +import net.minecraft.block.material.PushReaction; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.MoverType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Direction.AxisDirection; +import net.minecraft.util.ReuseableStream; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.shapes.ISelectionContext; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.world.IWorld; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public class MovingConstructHandler { + + static List renderedBBs = new LinkedList<>(); + static Map> movingPistons = new HashMap<>(); + + public void onLoadWorld(IWorld world) { + movingPistons.put(world, new ArrayList<>()); + Create.logger.info("Prepared Construct List for " + world.getDimension().getType().getRegistryName()); + } + + public void onUnloadWorld(IWorld world) { + movingPistons.remove(world); + Create.logger.info("Removed Construct List for " + world.getDimension().getType().getRegistryName()); + } + + public static void moveEntities(MechanicalPistonTileEntity te, float movementSpeed, Direction movementDirection, + float newOffset) { + World world = te.getWorld(); + Vec3d movementVec = new Vec3d(te.getBlockState().get(BlockStateProperties.FACING).getDirectionVec()); + Construct construct = te.movingConstruct; + + if (world.isRemote) { + renderedBBs.clear(); +// if (construct.collisionBoxFront != null) +// renderedBBs.add(construct.collisionBoxFront.offset(te.getConstructOffset(0))); +// if (construct.collisionBoxBack != null) +// renderedBBs.add(construct.collisionBoxBack.offset(te.getConstructOffset(0))); + + } + + if (construct.getCollisionBoxFront() != null) { + AxisAlignedBB constructBB = construct.getCollisionBoxFront().offset(te.getConstructOffset(0)).grow(.5f); + + for (Entity entity : world.getEntitiesWithinAABB((EntityType) null, constructBB, + e -> e.getPushReaction() == PushReaction.NORMAL)) { + + AxisAlignedBB entityScanBB = entity.getBoundingBox().offset(movementVec.scale(-1 * newOffset)) + .grow(.5f); + BlockPos min = new BlockPos(entityScanBB.minX, entityScanBB.minY, entityScanBB.minZ); + BlockPos max = new BlockPos(entityScanBB.maxX, entityScanBB.maxY, entityScanBB.maxZ); + + Stream hits = BlockPos.getAllInBox(min, max).filter(construct.blocks::containsKey) + .map(pos -> { + Vec3d vec = new Vec3d(pos).add(te.getConstructOffset(te.getMovementSpeed() > 0 ? 1 : 0)); + return construct.blocks.get(pos).state.getShape(world, new BlockPos(vec)).withOffset(vec.x, + vec.y, vec.z); + }); + ReuseableStream potentialHits = new ReuseableStream<>(hits); + + AxisAlignedBB entityBB = entity.getBoundingBox(); + Vec3d motion = entity.getMotion(); + Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(-movementSpeed).add(motion); + Vec3d allowedMovement = Entity.getAllowedMovement(movement, entityBB, world, + ISelectionContext.forEntity(entity), potentialHits); + + for (Object shape : potentialHits.createStream().toArray()) { + VoxelShape voxelShape = (VoxelShape) shape; + if (!entityBB.intersects(voxelShape.getBoundingBox())) + continue; + + Direction bestSide = Direction.DOWN; + double bestOffset = 100; + double finalOffset = 0; + + for (Direction face : Direction.values()) { + Axis axis = face.getAxis(); + double d = axis == Axis.X ? entityBB.getXSize() + : axis == Axis.Y ? entityBB.getYSize() : entityBB.getZSize(); + d = d + 1.5f; + + Vec3d nudge = new Vec3d(face.getDirectionVec()).scale(d); + AxisAlignedBB nudgedBB = entityBB.offset(nudge.getX(), nudge.getY(), nudge.getZ()); + double nudgeDistance = face.getAxisDirection() == AxisDirection.POSITIVE ? -d : d; + double offset = voxelShape.getAllowedOffset(face.getAxis(), nudgedBB, nudgeDistance); + double abs = Math.abs(nudgeDistance - offset); + if (abs < Math.abs(bestOffset) && abs != 0) { + bestOffset = abs; + finalOffset = abs; + bestSide = face; + } + } + + if (bestOffset != 0) { + entity.move(MoverType.SELF, new Vec3d(bestSide.getDirectionVec()).scale(finalOffset)); + switch (bestSide.getAxis()) { + case X: + entity.setMotion(0, motion.y, motion.z); + break; + case Y: + entity.setMotion(motion.x, bestSide == Direction.UP ? movementSpeed + 1 / 8f : 0, motion.z); + entity.fall(entity.fallDistance, 1); + entity.fallDistance = 0; + entity.onGround = true; + break; + case Z: + entity.setMotion(motion.x, motion.y, 0); + break; + } + + break; + } + } + + if (entity instanceof PlayerEntity && !world.isRemote) + return; + + if (!allowedMovement.equals(movement)) { + if (allowedMovement.y != movement.y) { + entity.fall(entity.fallDistance, 1); + entity.fallDistance = 0; + entity.onGround = true; + } + entity.setMotion(allowedMovement.subtract(movement.subtract(motion))); + } + + } + } + } + + public void add(MechanicalPistonTileEntity mechanicalPistonTileEntity) { + movingPistons.get(mechanicalPistonTileEntity.getWorld()).add(mechanicalPistonTileEntity); + } + + public void remove(MechanicalPistonTileEntity mechanicalPistonTileEntity) { + movingPistons.get(mechanicalPistonTileEntity.getWorld()).remove(mechanicalPistonTileEntity); + } + + public List getOtherMovingPistonsInWorld( + MechanicalPistonTileEntity mechanicalPistonTileEntity) { + return movingPistons.get(mechanicalPistonTileEntity.getWorld()); + } + +// @SubscribeEvent +// public static void onRenderWorld(RenderWorldLastEvent event) { +// for (AxisAlignedBB bb : renderedBBs) { +// TessellatorHelper.prepareForDrawing(); +// GlStateManager.disableTexture(); +// GlStateManager.lineWidth(3); +// int color = ColorHelper.rainbowColor(renderedBBs.indexOf(bb) * 170); +// WorldRenderer.drawSelectionBoundingBox(bb.grow(1 / 256f), (color >> 16 & 0xFF) / 256f, +// (color >> 8 & 0xFF) / 256f, (color & 0xFF) / 256f, 1); +// GlStateManager.lineWidth(1); +// GlStateManager.enableTexture(); +// TessellatorHelper.cleanUpAfterDrawing(); +// } +// } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/FrequencyHandler.java b/src/main/java/com/simibubi/create/modules/logistics/FrequencyHandler.java index d8a994b41..242ae957f 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/FrequencyHandler.java +++ b/src/main/java/com/simibubi/create/modules/logistics/FrequencyHandler.java @@ -51,12 +51,12 @@ public class FrequencyHandler { public void onLoadWorld(IWorld world) { connections.put(world, new HashMap<>()); - Create.logger.info("Prepared network space for " + world.getDimension().getType().getRegistryName()); + Create.logger.info("Prepared Network Space for " + world.getDimension().getType().getRegistryName()); } public void onUnloadWorld(IWorld world) { connections.remove(world); - Create.logger.info("Removed network space for " + world.getDimension().getType().getRegistryName()); + Create.logger.info("Removed Network Space for " + world.getDimension().getType().getRegistryName()); } private static Pair getNetworkKey(IHaveWireless actor) {