mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-24 14:06:42 +01:00
Mechanical Piston remastered
- Improved entity handling for moving constructs - Fixed Pistons colliding inconsistently after world reload
This commit is contained in:
parent
a62dc492d5
commit
4d065bebc1
6 changed files with 195 additions and 126 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<AxisAlignedBB> 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<VoxelShape> 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<VoxelShape> 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();
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
|
@ -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<MechanicalPistonTileEntity> 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<MechanicalPistonTileEntity> iterator = movingPistons.iterator();
|
||||
Iterator<MechanicalPistonTileEntity> iterator = Create.constructHandler.getOtherMovingPistonsInWorld(this)
|
||||
.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
MechanicalPistonTileEntity otherPiston = iterator.next();
|
||||
|
||||
|
|
|
@ -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<AxisAlignedBB> renderedBBs = new LinkedList<>();
|
||||
static Map<IWorld, List<MechanicalPistonTileEntity>> 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<VoxelShape> 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<VoxelShape> 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<MechanicalPistonTileEntity> 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();
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
|
@ -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<Frequency, Frequency> getNetworkKey(IHaveWireless actor) {
|
||||
|
|
Loading…
Reference in a new issue