Entering glue zone
- Reimplemented super glue as area-entities instead of individual connections
This commit is contained in:
parent
6ae6c4878f
commit
e1c3ad1a9b
25 changed files with 455 additions and 868 deletions
|
@ -6,7 +6,6 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntityRenderer;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraptionEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueInstance;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueRenderer;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionEntityRenderer;
|
||||
|
@ -34,25 +33,20 @@ import net.minecraft.world.entity.MobCategory;
|
|||
public class AllEntityTypes {
|
||||
|
||||
public static final EntityEntry<OrientedContraptionEntity> ORIENTED_CONTRAPTION = contraption("contraption",
|
||||
OrientedContraptionEntity::new, () -> OrientedContraptionEntityRenderer::new, 5, 3, true)
|
||||
.register();
|
||||
OrientedContraptionEntity::new, () -> OrientedContraptionEntityRenderer::new, 5, 3, true).register();
|
||||
public static final EntityEntry<ControlledContraptionEntity> CONTROLLED_CONTRAPTION =
|
||||
contraption("stationary_contraption", ControlledContraptionEntity::new, () -> ContraptionEntityRenderer::new,
|
||||
20, 40, false)
|
||||
.register();
|
||||
20, 40, false).register();
|
||||
public static final EntityEntry<GantryContraptionEntity> GANTRY_CONTRAPTION = contraption("gantry_contraption",
|
||||
GantryContraptionEntity::new, () -> ContraptionEntityRenderer::new, 10, 40, false)
|
||||
.register();
|
||||
GantryContraptionEntity::new, () -> ContraptionEntityRenderer::new, 10, 40, false).register();
|
||||
public static final EntityEntry<CarriageContraptionEntity> CARRIAGE_CONTRAPTION =
|
||||
contraption("carriage_contraption", CarriageContraptionEntity::new,
|
||||
() -> CarriageContraptionEntityRenderer::new, 15, 3, true)
|
||||
.instance(() -> CarriageContraptionInstance::new)
|
||||
.register();
|
||||
() -> CarriageContraptionEntityRenderer::new, 15, 3, true).instance(() -> CarriageContraptionInstance::new)
|
||||
.register();
|
||||
|
||||
public static final EntityEntry<SuperGlueEntity> SUPER_GLUE =
|
||||
register("super_glue", SuperGlueEntity::new, () -> SuperGlueRenderer::new, MobCategory.MISC, 10,
|
||||
Integer.MAX_VALUE, false, true, SuperGlueEntity::build).instance(() -> GlueInstance::new, false)
|
||||
.register();
|
||||
Integer.MAX_VALUE, false, true, SuperGlueEntity::build).register();
|
||||
|
||||
public static final EntityEntry<BlueprintEntity> CRAFTING_BLUEPRINT =
|
||||
register("crafting_blueprint", BlueprintEntity::new, () -> BlueprintRenderer::new, MobCategory.MISC, 10,
|
||||
|
|
|
@ -12,6 +12,7 @@ public enum AllSpecialTextures {
|
|||
CUTOUT_CHECKERED("cutout_checkerboard.png"),
|
||||
HIGHLIGHT_CHECKERED("highlighted_checkerboard.png"),
|
||||
SELECTION("selection.png"),
|
||||
GLUE("glue.png"),
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour;
|
|||
import com.simibubi.create.content.CreateItemGroup;
|
||||
import com.simibubi.create.content.contraptions.TorquePropagator;
|
||||
import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineInteractions;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueQueue;
|
||||
import com.simibubi.create.content.curiosities.weapons.BuiltinPotatoProjectileTypes;
|
||||
import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler;
|
||||
import com.simibubi.create.content.logistics.block.data.AllDataGathererBehaviours;
|
||||
|
@ -77,7 +76,6 @@ public class Create {
|
|||
public static final TorquePropagator TORQUE_PROPAGATOR = new TorquePropagator();
|
||||
public static final GlobalRailwayManager RAILWAYS = new GlobalRailwayManager();
|
||||
public static final ServerLagger LAGGER = new ServerLagger();
|
||||
public static final GlueQueue GLUE_QUEUE = new GlueQueue();
|
||||
public static final Random RANDOM = new Random();
|
||||
|
||||
private static final NonNullSupplier<CreateRegistrate> REGISTRATE = CreateRegistrate.lazy(ID);
|
||||
|
|
|
@ -42,7 +42,6 @@ import com.simibubi.create.content.contraptions.components.structureMovement.cha
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueHandler;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState;
|
||||
|
@ -101,6 +100,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|||
import net.minecraft.world.level.block.state.properties.ChestType;
|
||||
import net.minecraft.world.level.block.state.properties.PistonType;
|
||||
import net.minecraft.world.level.chunk.HashMapPalette;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
|
@ -137,12 +137,12 @@ public abstract class Contraption {
|
|||
protected Map<BlockPos, MountedFluidStorage> fluidStorage;
|
||||
protected List<MutablePair<StructureBlockInfo, MovementContext>> actors;
|
||||
protected Map<BlockPos, MovingInteractionBehaviour> interactors;
|
||||
protected Set<Pair<BlockPos, Direction>> superglue;
|
||||
protected List<AABB> superglue;
|
||||
protected List<BlockPos> seats;
|
||||
protected Map<UUID, Integer> seatMapping;
|
||||
protected Map<UUID, BlockFace> stabilizedSubContraptions;
|
||||
|
||||
private List<SuperGlueEntity> glueToRemove;
|
||||
private Set<SuperGlueEntity> glueToRemove;
|
||||
private Map<BlockPos, Entity> initialPassengers;
|
||||
private List<BlockFace> pendingSubContraptions;
|
||||
|
||||
|
@ -161,10 +161,10 @@ public abstract class Contraption {
|
|||
seats = new ArrayList<>();
|
||||
actors = new ArrayList<>();
|
||||
interactors = new HashMap<>();
|
||||
superglue = new HashSet<>();
|
||||
superglue = new ArrayList<>();
|
||||
seatMapping = new HashMap<>();
|
||||
fluidStorage = new HashMap<>();
|
||||
glueToRemove = new ArrayList<>();
|
||||
glueToRemove = new HashSet<>();
|
||||
initialPassengers = new HashMap<>();
|
||||
presentTileEntities = new HashMap<>();
|
||||
maybeInstancedTileEntities = new ArrayList<>();
|
||||
|
@ -389,8 +389,6 @@ public abstract class Contraption {
|
|||
if (!visited.contains(posDown) && AllBlocks.CART_ASSEMBLER.has(stateBelow))
|
||||
frontier.add(posDown);
|
||||
|
||||
Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos);
|
||||
|
||||
// Slime blocks and super glue drag adjacent blocks if possible
|
||||
for (Direction offset : Iterate.directions) {
|
||||
BlockPos offsetPos = pos.relative(offset);
|
||||
|
@ -404,7 +402,7 @@ public abstract class Contraption {
|
|||
}
|
||||
|
||||
boolean wasVisited = visited.contains(offsetPos);
|
||||
boolean faceHasGlue = superglue.containsKey(offset);
|
||||
boolean faceHasGlue = SuperGlueEntity.isGlued(world, pos, offset, glueToRemove);
|
||||
boolean blockAttachedTowardsFace =
|
||||
BlockMovementChecks.isBlockAttachedTowards(blockState, world, offsetPos, offset.getOpposite());
|
||||
boolean brittle = BlockMovementChecks.isBrittle(blockState);
|
||||
|
@ -425,8 +423,6 @@ public abstract class Contraption {
|
|||
if (!wasVisited && (canStick || blockAttachedTowardsFace || faceHasGlue
|
||||
|| (offset == forcedDirection && !BlockMovementChecks.isNotSupportive(state, forcedDirection))))
|
||||
frontier.add(offsetPos);
|
||||
if (faceHasGlue)
|
||||
addGlue(superglue.get(offset));
|
||||
}
|
||||
|
||||
addBlock(pos, capture(world, pos));
|
||||
|
@ -678,13 +674,6 @@ public abstract class Contraption {
|
|||
return nbt;
|
||||
}
|
||||
|
||||
protected void addGlue(SuperGlueEntity entity) {
|
||||
BlockPos pos = entity.getHangingPosition();
|
||||
Direction direction = entity.getFacingDirection();
|
||||
this.superglue.add(Pair.of(toLocalPos(pos), direction));
|
||||
glueToRemove.add(entity);
|
||||
}
|
||||
|
||||
protected BlockPos toLocalPos(BlockPos globalPos) {
|
||||
return globalPos.subtract(anchor);
|
||||
}
|
||||
|
@ -718,8 +707,8 @@ public abstract class Contraption {
|
|||
});
|
||||
|
||||
superglue.clear();
|
||||
NBTHelper.iterateCompoundList(nbt.getList("Superglue", Tag.TAG_COMPOUND), c -> superglue.add(
|
||||
Pair.of(NbtUtils.readBlockPos(c.getCompound("Pos")), Direction.from3DDataValue(c.getByte("Direction")))));
|
||||
NBTHelper.iterateCompoundList(nbt.getList("Superglue", Tag.TAG_COMPOUND),
|
||||
c -> superglue.add(SuperGlueEntity.readBoundingBox(c)));
|
||||
|
||||
seats.clear();
|
||||
NBTHelper.iterateCompoundList(nbt.getList("Seats", Tag.TAG_COMPOUND), c -> seats.add(NbtUtils.readBlockPos(c)));
|
||||
|
@ -802,11 +791,9 @@ public abstract class Contraption {
|
|||
ListTag superglueNBT = new ListTag();
|
||||
ListTag storageNBT = new ListTag();
|
||||
if (!spawnPacket) {
|
||||
for (Pair<BlockPos, Direction> glueEntry : superglue) {
|
||||
for (AABB glueEntry : superglue) {
|
||||
CompoundTag c = new CompoundTag();
|
||||
c.put("Pos", NbtUtils.writeBlockPos(glueEntry.getKey()));
|
||||
c.putByte("Direction", (byte) glueEntry.getValue()
|
||||
.get3DDataValue());
|
||||
SuperGlueEntity.writeBoundingBox(c, glueEntry);
|
||||
superglueNBT.add(c);
|
||||
}
|
||||
|
||||
|
@ -978,7 +965,17 @@ public abstract class Contraption {
|
|||
.forEach(MountedStorage::removeStorageFromWorld);
|
||||
fluidStorage.values()
|
||||
.forEach(MountedFluidStorage::removeStorageFromWorld);
|
||||
glueToRemove.forEach(SuperGlueEntity::discard);
|
||||
|
||||
glueToRemove.forEach(glue -> {
|
||||
superglue.add(glue.getBoundingBox()
|
||||
.move(Vec3.atLowerCornerOf(offset.offset(anchor))
|
||||
.scale(-1)));
|
||||
glue.discard();
|
||||
});
|
||||
|
||||
List<BoundingBox> minimisedGlue = new ArrayList<>();
|
||||
for (int i = 0; i < superglue.size(); i++)
|
||||
minimisedGlue.add(null);
|
||||
|
||||
for (boolean brittles : Iterate.trueAndFalse) {
|
||||
for (Iterator<StructureBlockInfo> iterator = blocks.values()
|
||||
|
@ -987,6 +984,18 @@ public abstract class Contraption {
|
|||
if (brittles != BlockMovementChecks.isBrittle(block.state))
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < superglue.size(); i++) {
|
||||
AABB aabb = superglue.get(i);
|
||||
if (aabb == null
|
||||
|| !aabb.contains(block.pos.getX() + .5, block.pos.getY() + .5, block.pos.getZ() + .5))
|
||||
continue;
|
||||
if (minimisedGlue.get(i) == null)
|
||||
minimisedGlue.set(i, new BoundingBox(block.pos));
|
||||
else
|
||||
minimisedGlue.get(i)
|
||||
.encapsulate(block.pos);
|
||||
}
|
||||
|
||||
BlockPos add = block.pos.offset(anchor)
|
||||
.offset(offset);
|
||||
if (customBlockRemoval(world, add, block.state))
|
||||
|
@ -1008,6 +1017,16 @@ public abstract class Contraption {
|
|||
world.setBlock(add, Blocks.AIR.defaultBlockState(), flags);
|
||||
}
|
||||
}
|
||||
|
||||
superglue.clear();
|
||||
for (BoundingBox box : minimisedGlue) {
|
||||
if (box == null)
|
||||
continue;
|
||||
AABB bb = new AABB(box.minX(), box.minY(), box.minZ(), box.maxX() + 1, box.maxY() + 1, box.maxZ() + 1);
|
||||
if (bb.getSize() > 1.01)
|
||||
superglue.add(bb);
|
||||
}
|
||||
|
||||
for (StructureBlockInfo block : blocks.values()) {
|
||||
BlockPos add = block.pos.offset(anchor)
|
||||
.offset(offset);
|
||||
|
@ -1074,10 +1093,10 @@ public abstract class Contraption {
|
|||
}
|
||||
|
||||
world.destroyBlock(targetPos, true);
|
||||
|
||||
|
||||
if (AllBlocks.SHAFT.has(state))
|
||||
state = ShaftBlock.pickCorrectShaftType(state, world, targetPos);
|
||||
|
||||
|
||||
world.setBlock(targetPos, state, Block.UPDATE_MOVE_BY_PISTON | Block.UPDATE_ALL);
|
||||
|
||||
boolean verticalRotation = transform.rotationAxis == null || transform.rotationAxis.isHorizontal();
|
||||
|
@ -1137,15 +1156,11 @@ public abstract class Contraption {
|
|||
for (int i = 0; i < fluidInventory.getTanks(); i++)
|
||||
fluidInventory.drain(fluidInventory.getFluidInTank(i), FluidAction.EXECUTE);
|
||||
|
||||
for (Pair<BlockPos, Direction> pair : superglue) {
|
||||
BlockPos targetPos = transform.apply(pair.getKey());
|
||||
Direction targetFacing = transform.transformFacing(pair.getValue());
|
||||
|
||||
SuperGlueEntity entity = new SuperGlueEntity(world, targetPos, targetFacing);
|
||||
if (entity.onValidSurface()) {
|
||||
if (!world.isClientSide)
|
||||
world.addFreshEntity(entity);
|
||||
}
|
||||
for (AABB box : superglue) {
|
||||
box = new AABB(transform.apply(new Vec3(box.minX, box.minY, box.minZ)),
|
||||
transform.apply(new Vec3(box.maxX, box.maxY, box.maxZ)));
|
||||
if (!world.isClientSide)
|
||||
world.addFreshEntity(new SuperGlueEntity(world, box));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
|
||||
|
||||
import com.jozufozu.flywheel.api.Instancer;
|
||||
import com.jozufozu.flywheel.api.MaterialGroup;
|
||||
import com.jozufozu.flywheel.api.MaterialManager;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
|
||||
import com.jozufozu.flywheel.core.Materials;
|
||||
import com.jozufozu.flywheel.core.instancing.ConditionalInstance;
|
||||
import com.jozufozu.flywheel.core.materials.oriented.OrientedData;
|
||||
import com.mojang.math.Quaternion;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
|
||||
public class GlueInstance extends EntityInstance<SuperGlueEntity> implements TickableInstance {
|
||||
|
||||
private static final ResourceLocation TEXTURE = Create.asResource("textures/entity/super_glue/slime.png");
|
||||
|
||||
private final Quaternion rotation;
|
||||
protected ConditionalInstance<OrientedData> model;
|
||||
|
||||
public GlueInstance(MaterialManager materialManager, SuperGlueEntity entity) {
|
||||
super(materialManager, entity);
|
||||
|
||||
Instancer<OrientedData> instancer = getInstancer(materialManager, entity);
|
||||
|
||||
Direction face = entity.getFacingDirection();
|
||||
rotation = new Quaternion(AngleHelper.verticalAngle(face), AngleHelper.horizontalAngle(face), 0, true);
|
||||
|
||||
model = new ConditionalInstance<>(instancer)
|
||||
.withCondition(this::shouldShow)
|
||||
.withSetupFunc(this::positionModel)
|
||||
.update();
|
||||
}
|
||||
|
||||
private Instancer<OrientedData> getInstancer(MaterialManager materialManager, SuperGlueEntity entity) {
|
||||
MaterialGroup group = GlueModel.USE_ATLAS ? materialManager.defaultCutout() : materialManager.cutout(RenderType.entityCutout(TEXTURE));
|
||||
|
||||
return group.material(Materials.ORIENTED).model(entity.getType(), GlueModel::get);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
model.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
model.delete();
|
||||
}
|
||||
|
||||
private void positionModel(OrientedData model) {
|
||||
|
||||
model.setPosition(getInstancePosition())
|
||||
.setPivot(0, 0, 0)
|
||||
.setRotation(rotation);
|
||||
|
||||
updateLight(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
model.get().ifPresent(this::updateLight);
|
||||
}
|
||||
|
||||
private void updateLight(OrientedData model) {
|
||||
BlockPos pos = entity.getHangingPosition();
|
||||
model.setBlockLight(world.getBrightness(LightLayer.BLOCK, pos))
|
||||
.setSkyLight(world.getBrightness(LightLayer.SKY, pos));
|
||||
}
|
||||
|
||||
private boolean shouldShow() {
|
||||
Player player = Minecraft.getInstance().player;
|
||||
|
||||
return entity.isVisible()
|
||||
|| AllItems.SUPER_GLUE.isIn(player.getMainHandItem())
|
||||
|| AllItems.SUPER_GLUE.isIn(player.getOffhandItem());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||
import com.jozufozu.flywheel.core.Formats;
|
||||
import com.jozufozu.flywheel.core.model.Model;
|
||||
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
|
||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||
import com.simibubi.create.AllStitchedTextures;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class GlueModel implements Model {
|
||||
|
||||
public static final GlueModel INSTANCE = new GlueModel();
|
||||
static final boolean USE_ATLAS = false;
|
||||
|
||||
public static GlueModel get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private final VertexList reader;
|
||||
|
||||
private GlueModel() {
|
||||
PosTexNormalWriterUnsafe writer = Formats.POS_TEX_NORMAL.createWriter(MemoryTracker.create(size()));
|
||||
createGlueModel(writer);
|
||||
reader = writer.intoReader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "glue";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int vertexCount() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexList getReader() {
|
||||
return reader;
|
||||
}
|
||||
|
||||
public static void createGlueModel(PosTexNormalWriterUnsafe buffer) {
|
||||
Vec3 diff = Vec3.atLowerCornerOf(Direction.SOUTH.getNormal());
|
||||
Vec3 extension = diff.normalize()
|
||||
.scale(1 / 32f - 1 / 128f);
|
||||
|
||||
Vec3 plane = VecHelper.axisAlingedPlaneOf(diff);
|
||||
Direction.Axis axis = Direction.getNearest(diff.x, diff.y, diff.z)
|
||||
.getAxis();
|
||||
|
||||
Vec3 start = Vec3.ZERO.subtract(extension);
|
||||
Vec3 end = Vec3.ZERO.add(extension);
|
||||
|
||||
plane = plane.scale(1 / 2f);
|
||||
Vec3 a1 = plane.add(start);
|
||||
Vec3 b1 = plane.add(end);
|
||||
plane = VecHelper.rotate(plane, -90, axis);
|
||||
Vec3 a2 = plane.add(start);
|
||||
Vec3 b2 = plane.add(end);
|
||||
plane = VecHelper.rotate(plane, -90, axis);
|
||||
Vec3 a3 = plane.add(start);
|
||||
Vec3 b3 = plane.add(end);
|
||||
plane = VecHelper.rotate(plane, -90, axis);
|
||||
Vec3 a4 = plane.add(start);
|
||||
Vec3 b4 = plane.add(end);
|
||||
|
||||
float minU;
|
||||
float maxU;
|
||||
float minV;
|
||||
float maxV;
|
||||
|
||||
if (USE_ATLAS) {
|
||||
TextureAtlasSprite sprite = AllStitchedTextures.SUPER_GLUE.get();
|
||||
minU = sprite.getU0();
|
||||
maxU = sprite.getU1();
|
||||
minV = sprite.getV0();
|
||||
maxV = sprite.getV1();
|
||||
} else {
|
||||
minU = minV = 0;
|
||||
maxU = maxV = 1;
|
||||
}
|
||||
|
||||
// inside quad
|
||||
buffer.putVertex((float) a1.x, (float) a1.y, (float) a1.z, 0, 0, -1, maxU, minV);
|
||||
buffer.putVertex((float) a2.x, (float) a2.y, (float) a2.z, 0, 0, -1, maxU, maxV);
|
||||
buffer.putVertex((float) a3.x, (float) a3.y, (float) a3.z, 0, 0, -1, minU, maxV);
|
||||
buffer.putVertex((float) a4.x, (float) a4.y, (float) a4.z, 0, 0, -1, minU, minV);
|
||||
// outside quad
|
||||
buffer.putVertex((float) b4.x, (float) b4.y, (float) b4.z, 0, 0, 1f, minU, minV);
|
||||
buffer.putVertex((float) b3.x, (float) b3.y, (float) b3.z, 0, 0, 1f, minU, maxV);
|
||||
buffer.putVertex((float) b2.x, (float) b2.y, (float) b2.z, 0, 0, 1f, maxU, maxV);
|
||||
buffer.putVertex((float) b1.x, (float) b1.y, (float) b1.z, 0, 0, 1f, maxU, minV);
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.WorldAttached;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
public class GlueQueue {
|
||||
|
||||
private WorldAttached<List<BlockFace>> QUEUED_GLUE = new WorldAttached<>(level -> new LinkedList<>());
|
||||
|
||||
public void tick(Level level) {
|
||||
List<BlockFace> list = QUEUED_GLUE.get(level);
|
||||
if (list.isEmpty())
|
||||
return;
|
||||
BlockFace next = list.remove(0);
|
||||
if (!level.isLoaded(next.getPos()))
|
||||
return;
|
||||
|
||||
SuperGlueEntity entity = new SuperGlueEntity(level, next.getPos(), next.getFace());
|
||||
level.addFreshEntity(entity);
|
||||
AllSoundEvents.SLIME_ADDED.playFrom(entity, 0.125F, Mth.clamp(8f / (list.size() + 1), 0.75f, 1f));
|
||||
|
||||
AllPackets.channel.send(PacketDistributor.ALL.noArg(),
|
||||
new GlueEffectPacket(entity.getHangingPosition(), entity.getFacingDirection()
|
||||
.getOpposite(), false));
|
||||
}
|
||||
|
||||
public void add(Level level, Collection<BlockFace> entries) {
|
||||
QUEUED_GLUE.get(level)
|
||||
.addAll(entries);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import java.util.Set;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllEntityTypes;
|
||||
|
@ -15,23 +13,19 @@ import com.simibubi.create.content.contraptions.components.structureMovement.cha
|
|||
import com.simibubi.create.content.schematics.ISpecialEntityItemRequirement;
|
||||
import com.simibubi.create.content.schematics.ItemRequirement;
|
||||
import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.core.Direction.AxisDirection;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
|
@ -39,14 +33,11 @@ import net.minecraft.world.entity.Entity;
|
|||
import net.minecraft.world.entity.EntityDimensions;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LightningBolt;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.MoverType;
|
||||
import net.minecraft.world.entity.Pose;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.DirectionalBlock;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
|
@ -54,145 +45,51 @@ import net.minecraft.world.level.block.Rotation;
|
|||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.HitResult.Type;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.util.FakePlayer;
|
||||
import net.minecraftforge.entity.IEntityAdditionalSpawnData;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
public class SuperGlueEntity extends Entity
|
||||
implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement {
|
||||
public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement {
|
||||
|
||||
private int validationTimer;
|
||||
protected BlockPos hangingPosition;
|
||||
protected Direction facingDirection = Direction.SOUTH;
|
||||
public static AABB span(BlockPos startPos, BlockPos endPos) {
|
||||
return new AABB(startPos, endPos).expandTowards(1, 1, 1);
|
||||
}
|
||||
|
||||
public static boolean isGlued(LevelAccessor level, BlockPos blockPos, Direction direction,
|
||||
Set<SuperGlueEntity> cached) {
|
||||
BlockPos targetPos = blockPos.relative(direction);
|
||||
if (cached != null)
|
||||
for (SuperGlueEntity glueEntity : cached)
|
||||
if (glueEntity.contains(blockPos) && glueEntity.contains(targetPos))
|
||||
return true;
|
||||
for (SuperGlueEntity glueEntity : level.getEntitiesOfClass(SuperGlueEntity.class, span(blockPos, targetPos))) {
|
||||
if (!glueEntity.contains(blockPos) || !glueEntity.contains(targetPos))
|
||||
continue;
|
||||
if (cached != null)
|
||||
cached.add(glueEntity);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public SuperGlueEntity(EntityType<?> type, Level world) {
|
||||
super(type, world);
|
||||
}
|
||||
|
||||
public SuperGlueEntity(Level world, BlockPos pos, Direction direction) {
|
||||
public SuperGlueEntity(Level world, AABB boundingBox) {
|
||||
this(AllEntityTypes.SUPER_GLUE.get(), world);
|
||||
hangingPosition = pos;
|
||||
facingDirection = direction;
|
||||
updateFacingWithBoundingBox();
|
||||
setBoundingBox(boundingBox);
|
||||
resetPositionToBB();
|
||||
}
|
||||
|
||||
public void resetPositionToBB() {
|
||||
AABB bb = getBoundingBox();
|
||||
setPosRaw(bb.getCenter().x, bb.minY, bb.getCenter().z);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData() {}
|
||||
|
||||
public int getWidthPixels() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
public int getHeightPixels() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
public void onBroken(@Nullable Entity breaker) {
|
||||
playSound(SoundEvents.SLIME_SQUISH_SMALL, 1.0F, 1.0F);
|
||||
if (onValidSurface()) {
|
||||
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
||||
new GlueEffectPacket(getHangingPosition(), getFacingDirection().getOpposite(), false));
|
||||
AllSoundEvents.SLIME_ADDED.playFrom(this, 0.5F, 0.5F);
|
||||
}
|
||||
}
|
||||
|
||||
public void playPlaceSound() {
|
||||
AllSoundEvents.SLIME_ADDED.playFrom(this, 0.5F, 0.75F);
|
||||
}
|
||||
|
||||
protected void updateFacingWithBoundingBox() {
|
||||
Validate.notNull(getFacingDirection());
|
||||
if (getFacingDirection().getAxis()
|
||||
.isHorizontal()) {
|
||||
setXRot(0);
|
||||
setYRot(getFacingDirection().get2DDataValue() * 90);
|
||||
} else {
|
||||
setXRot(-90 * getFacingDirection().getAxisDirection()
|
||||
.getStep());
|
||||
setYRot(0);
|
||||
}
|
||||
|
||||
this.xRotO = this.getXRot();
|
||||
this.yRotO = this.getYRot();
|
||||
this.updateBoundingBox();
|
||||
}
|
||||
|
||||
protected void updateBoundingBox() {
|
||||
if (this.getFacingDirection() != null) {
|
||||
double offset = 0.5 - 1 / 256d;
|
||||
double x = hangingPosition.getX() + 0.5 - facingDirection.getStepX() * offset;
|
||||
double y = hangingPosition.getY() + 0.5 - facingDirection.getStepY() * offset;
|
||||
double z = hangingPosition.getZ() + 0.5 - facingDirection.getStepZ() * offset;
|
||||
this.setPosRaw(x, y, z);
|
||||
double w = getWidthPixels();
|
||||
double h = getHeightPixels();
|
||||
double l = getWidthPixels();
|
||||
Axis axis = this.getFacingDirection()
|
||||
.getAxis();
|
||||
double depth = 2 - 1 / 128f;
|
||||
|
||||
switch (axis) {
|
||||
case X -> w = depth;
|
||||
case Y -> h = depth;
|
||||
case Z -> l = depth;
|
||||
}
|
||||
|
||||
w = w / 32.0D;
|
||||
h = h / 32.0D;
|
||||
l = l / 32.0D;
|
||||
this.setBoundingBox(new AABB(x - w, y - h, z - l, x + w, y + h, z + l));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (this.validationTimer++ == 10 && !this.level.isClientSide) {
|
||||
this.validationTimer = 0;
|
||||
if (isAlive() && !this.onValidSurface()) {
|
||||
kill();
|
||||
onBroken(null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
if (!isAlive())
|
||||
return false;
|
||||
if (level instanceof WrappedWorld)
|
||||
return true;
|
||||
|
||||
BlockPos pos = hangingPosition;
|
||||
BlockPos pos2 = pos.relative(getFacingDirection().getOpposite());
|
||||
return isValidFace(level, pos2, getFacingDirection()) != isValidFace(level, pos,
|
||||
getFacingDirection().getOpposite());
|
||||
}
|
||||
|
||||
public boolean onValidSurface() {
|
||||
BlockPos pos = hangingPosition;
|
||||
BlockPos pos2 = hangingPosition.relative(getFacingDirection().getOpposite());
|
||||
if (level.isOutsideBuildHeight(pos2))
|
||||
return false;
|
||||
if (!level.isLoaded(pos) || !level.isLoaded(pos2))
|
||||
return true;
|
||||
if (!isValidFace(level, pos2, getFacingDirection())
|
||||
&& !isValidFace(level, pos, getFacingDirection().getOpposite()))
|
||||
return false;
|
||||
if (isSideSticky(level, pos2, getFacingDirection())
|
||||
|| isSideSticky(level, pos, getFacingDirection().getOpposite()))
|
||||
return false;
|
||||
return level.getEntities(this, getBoundingBox(), e -> e instanceof SuperGlueEntity)
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
public static boolean isValidFace(Level world, BlockPos pos, Direction direction) {
|
||||
BlockState state = world.getBlockState(pos);
|
||||
if (BlockMovementChecks.isBlockAttachedTowards(state, world, pos, direction))
|
||||
|
@ -237,61 +134,36 @@ public class SuperGlueEntity extends Entity
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPickable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean skipAttackInteraction(Entity entity) {
|
||||
return entity instanceof Player ? hurt(DamageSource.playerAttack((Player) entity), 0) : false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction getDirection() {
|
||||
return this.getFacingDirection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hurt(DamageSource source, float amount) {
|
||||
if (this.isInvulnerableTo(source))
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean mobGriefing = level.getGameRules()
|
||||
.getBoolean(GameRules.RULE_MOBGRIEFING);
|
||||
Entity trueSource = source.getEntity();
|
||||
if (!mobGriefing && trueSource instanceof Mob)
|
||||
return false;
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (getBoundingBox().getXsize() == 0)
|
||||
discard();
|
||||
}
|
||||
|
||||
Entity immediateSource = source.getDirectEntity();
|
||||
if (!isVisible() && immediateSource instanceof Player) {
|
||||
if (!AllItems.SUPER_GLUE.isIn(((Player) immediateSource).getMainHandItem()))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isAlive() && !level.isClientSide) {
|
||||
onBroken(source.getEntity());
|
||||
kill();
|
||||
markHurt();
|
||||
}
|
||||
|
||||
return true;
|
||||
@Override
|
||||
public void setPos(double x, double y, double z) {
|
||||
setPosRaw(x, y, z);
|
||||
getBoundingBox().move(getBoundingBox().getCenter()
|
||||
.scale(-1)
|
||||
.add(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(MoverType typeIn, Vec3 pos) {
|
||||
if (!level.isClientSide && isAlive() && pos.lengthSqr() > 0.0D) {
|
||||
if (!level.isClientSide && isAlive() && pos.lengthSqr() > 0.0D)
|
||||
discard();
|
||||
onBroken(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(double x, double y, double z) {
|
||||
if (!level.isClientSide && isAlive() && x * x + y * y + z * z > 0.0D) {
|
||||
if (!level.isClientSide && isAlive() && x * x + y * y + z * z > 0.0D)
|
||||
discard();
|
||||
onBroken(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -299,9 +171,8 @@ public class SuperGlueEntity extends Entity
|
|||
return 0.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getPickedResult(HitResult target) {
|
||||
return AllItems.SUPER_GLUE.asStack();
|
||||
public void playPlaceSound() {
|
||||
AllSoundEvents.SLIME_ADDED.playFrom(this, 0.5F, 0.75F);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -311,79 +182,30 @@ public class SuperGlueEntity extends Entity
|
|||
|
||||
@Override
|
||||
public InteractionResult interact(Player player, InteractionHand hand) {
|
||||
if (player instanceof FakePlayer)
|
||||
return InteractionResult.PASS;
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||
triggerPlaceBlock(player, hand);
|
||||
});
|
||||
return InteractionResult.CONSUME;
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private void triggerPlaceBlock(Player player, InteractionHand hand) {
|
||||
if (!(player instanceof LocalPlayer))
|
||||
return;
|
||||
if (!(player.level instanceof ClientLevel))
|
||||
return;
|
||||
|
||||
LocalPlayer cPlayer = (LocalPlayer) player;
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
HitResult ray = cPlayer.pick(mc.gameMode.getPickRange(), AnimationTickHolder.getPartialTicks(), false);
|
||||
|
||||
if (!(ray instanceof BlockHitResult))
|
||||
return;
|
||||
if (ray.getType() == Type.MISS)
|
||||
return;
|
||||
BlockHitResult blockRay = (BlockHitResult) ray;
|
||||
BlockFace rayFace = new BlockFace(blockRay.getBlockPos(), blockRay.getDirection());
|
||||
BlockFace hangingFace = new BlockFace(getHangingPosition(), getFacingDirection().getOpposite());
|
||||
if (!rayFace.isEquivalent(hangingFace))
|
||||
return;
|
||||
|
||||
for (InteractionHand handIn : InteractionHand.values()) {
|
||||
ItemStack itemstack = cPlayer.getItemInHand(handIn);
|
||||
int countBefore = itemstack.getCount();
|
||||
InteractionResult actionResultType =
|
||||
mc.gameMode.useItemOn(cPlayer, (ClientLevel) cPlayer.level, handIn, blockRay);
|
||||
if (actionResultType != InteractionResult.SUCCESS)
|
||||
return;
|
||||
|
||||
cPlayer.swing(handIn);
|
||||
if (!itemstack.isEmpty() && (itemstack.getCount() != countBefore || mc.gameMode.hasInfiniteItems()))
|
||||
mc.gameRenderer.itemInHandRenderer.itemUsed(handIn);
|
||||
return;
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag compound) {
|
||||
compound.putByte("Facing", (byte) this.getFacingDirection()
|
||||
.get3DDataValue());
|
||||
BlockPos blockpos = this.getHangingPosition();
|
||||
compound.putInt("TileX", blockpos.getX());
|
||||
compound.putInt("TileY", blockpos.getY());
|
||||
compound.putInt("TileZ", blockpos.getZ());
|
||||
Vec3 position = position();
|
||||
writeBoundingBox(compound, getBoundingBox().move(position.scale(-1)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag compound) {
|
||||
this.hangingPosition =
|
||||
new BlockPos(compound.getInt("TileX"), compound.getInt("TileY"), compound.getInt("TileZ"));
|
||||
this.facingDirection = Direction.from3DDataValue(compound.getByte("Facing"));
|
||||
updateFacingWithBoundingBox();
|
||||
Vec3 position = position();
|
||||
setBoundingBox(readBoundingBox(compound).move(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemEntity spawnAtLocation(ItemStack stack, float yOffset) {
|
||||
float xOffset = (float) this.getFacingDirection()
|
||||
.getStepX() * 0.15F;
|
||||
float zOffset = (float) this.getFacingDirection()
|
||||
.getStepZ() * 0.15F;
|
||||
ItemEntity itementity =
|
||||
new ItemEntity(this.level, this.getX() + xOffset, this.getY() + yOffset, this.getZ() + zOffset, stack);
|
||||
itementity.setDefaultPickUpDelay();
|
||||
this.level.addFreshEntity(itementity);
|
||||
return itementity;
|
||||
public static void writeBoundingBox(CompoundTag compound, AABB bb) {
|
||||
compound.put("From", VecHelper.writeNBT(new Vec3(bb.minX, bb.minY, bb.minZ)));
|
||||
compound.put("To", VecHelper.writeNBT(new Vec3(bb.maxX, bb.maxY, bb.maxZ)));
|
||||
}
|
||||
|
||||
public static AABB readBoundingBox(CompoundTag compound) {
|
||||
Vec3 from = VecHelper.readNBT(compound.getList("From", Tag.TAG_DOUBLE));
|
||||
Vec3 to = VecHelper.readNBT(compound.getList("To", Tag.TAG_DOUBLE));
|
||||
return new AABB(from, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -391,51 +213,17 @@ public class SuperGlueEntity extends Entity
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPos(double x, double y, double z) {
|
||||
hangingPosition = new BlockPos(x, y, z);
|
||||
updateBoundingBox();
|
||||
hasImpulse = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float rotate(Rotation transformRotation) {
|
||||
if (this.getFacingDirection()
|
||||
.getAxis() != Direction.Axis.Y) {
|
||||
switch (transformRotation) {
|
||||
case CLOCKWISE_180:
|
||||
facingDirection = facingDirection.getOpposite();
|
||||
break;
|
||||
case COUNTERCLOCKWISE_90:
|
||||
facingDirection = facingDirection.getCounterClockWise();
|
||||
break;
|
||||
case CLOCKWISE_90:
|
||||
facingDirection = facingDirection.getClockWise();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float f = Mth.wrapDegrees(this.getYRot());
|
||||
return switch (transformRotation) {
|
||||
case CLOCKWISE_180 -> f + 180.0F;
|
||||
case COUNTERCLOCKWISE_90 -> f + 90.0F;
|
||||
case CLOCKWISE_90 -> f + 270.0F;
|
||||
default -> f;
|
||||
};
|
||||
}
|
||||
|
||||
public BlockPos getHangingPosition() {
|
||||
return this.hangingPosition;
|
||||
AABB bb = getBoundingBox().move(position().scale(-1));
|
||||
if (transformRotation == Rotation.CLOCKWISE_90 || transformRotation == Rotation.COUNTERCLOCKWISE_90)
|
||||
setBoundingBox(new AABB(bb.minZ, bb.minY, bb.minX, bb.maxZ, bb.maxY, bb.maxX).move(position()));
|
||||
return super.rotate(transformRotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float mirror(Mirror transformMirror) {
|
||||
return this.rotate(transformMirror.getRotation(this.getFacingDirection()));
|
||||
}
|
||||
|
||||
public Direction getAttachedDirection(BlockPos pos) {
|
||||
return !pos.equals(hangingPosition) ? getFacingDirection() : getFacingDirection().getOpposite();
|
||||
return super.mirror(transformMirror);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -467,10 +255,6 @@ public class SuperGlueEntity extends Entity
|
|||
readAdditionalSaveData(additionalData.readNbt());
|
||||
}
|
||||
|
||||
public Direction getFacingDirection() {
|
||||
return facingDirection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemRequirement getRequiredItems() {
|
||||
return new ItemRequirement(ItemUseType.DAMAGE, AllItems.SUPER_GLUE.get());
|
||||
|
@ -480,4 +264,53 @@ public class SuperGlueEntity extends Entity
|
|||
public boolean isIgnoringBlockTriggers() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean contains(BlockPos pos) {
|
||||
return getBoundingBox().contains(Vec3.atCenterOf(pos));
|
||||
}
|
||||
|
||||
public void spawnParticles() {
|
||||
AABB bb = getBoundingBox();
|
||||
Vec3 origin = new Vec3(bb.minX, bb.minY, bb.minZ);
|
||||
Vec3 extents = new Vec3(bb.getXsize(), bb.getYsize(), bb.getZsize());
|
||||
|
||||
if (!(level instanceof ServerLevel slevel))
|
||||
return;
|
||||
|
||||
for (Axis axis : Iterate.axes) {
|
||||
AxisDirection positive = AxisDirection.POSITIVE;
|
||||
double max = axis.choose(extents.x, extents.y, extents.z);
|
||||
Vec3 normal = Vec3.atLowerCornerOf(Direction.fromAxisAndDirection(axis, positive)
|
||||
.getNormal());
|
||||
for (Axis axis2 : Iterate.axes) {
|
||||
if (axis2 == axis)
|
||||
continue;
|
||||
double max2 = axis2.choose(extents.x, extents.y, extents.z);
|
||||
Vec3 normal2 = Vec3.atLowerCornerOf(Direction.fromAxisAndDirection(axis2, positive)
|
||||
.getNormal());
|
||||
for (Axis axis3 : Iterate.axes) {
|
||||
if (axis3 == axis2 || axis3 == axis)
|
||||
continue;
|
||||
double max3 = axis3.choose(extents.x, extents.y, extents.z);
|
||||
Vec3 normal3 = Vec3.atLowerCornerOf(Direction.fromAxisAndDirection(axis3, positive)
|
||||
.getNormal());
|
||||
|
||||
for (int i = 0; i <= max * 2; i++) {
|
||||
for (int o1 : Iterate.zeroAndOne) {
|
||||
for (int o2 : Iterate.zeroAndOne) {
|
||||
Vec3 v = origin.add(normal.scale(i / 2f))
|
||||
.add(normal2.scale(max2 * o1))
|
||||
.add(normal3.scale(max3 * o2));
|
||||
|
||||
slevel.sendParticles(ParticleTypes.ITEM_SLIME, v.x, v.y, v.z, 1, 0, 0, 0, 0);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
|
||||
import com.simibubi.create.foundation.utility.worldWrappers.RayTraceWorld;
|
||||
|
||||
|
@ -21,7 +22,6 @@ import net.minecraft.world.level.ClipContext;
|
|||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult.Type;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
@ -34,14 +34,6 @@ import net.minecraftforge.network.PacketDistributor;
|
|||
@EventBusSubscriber
|
||||
public class SuperGlueHandler {
|
||||
|
||||
public static Map<Direction, SuperGlueEntity> gatherGlue(LevelAccessor world, BlockPos pos) {
|
||||
List<SuperGlueEntity> entities = world.getEntitiesOfClass(SuperGlueEntity.class, new AABB(pos));
|
||||
Map<Direction, SuperGlueEntity> map = new HashMap<>();
|
||||
for (SuperGlueEntity entity : entities)
|
||||
map.put(entity.getAttachedDirection(pos), entity);
|
||||
return map;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void glueListensForBlockPlacement(EntityPlaceEvent event) {
|
||||
LevelAccessor world = event.getWorld();
|
||||
|
@ -53,10 +45,14 @@ public class SuperGlueHandler {
|
|||
if (world.isClientSide())
|
||||
return;
|
||||
|
||||
Map<Direction, SuperGlueEntity> gatheredGlue = gatherGlue(world, pos);
|
||||
for (Direction direction : gatheredGlue.keySet())
|
||||
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> entity),
|
||||
new GlueEffectPacket(pos, direction, true));
|
||||
Set<SuperGlueEntity> cached = new HashSet<>();
|
||||
for (Direction direction : Iterate.directions) {
|
||||
BlockPos relative = pos.relative(direction);
|
||||
if (SuperGlueEntity.isGlued(world, pos, direction, cached)
|
||||
&& BlockMovementChecks.isMovementNecessary(world.getBlockState(relative), entity.level, relative))
|
||||
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> entity),
|
||||
new GlueEffectPacket(pos, direction, true));
|
||||
}
|
||||
|
||||
if (entity instanceof Player)
|
||||
glueInOffHandAppliesOnBlockPlace(event, pos, (Player) entity);
|
||||
|
@ -80,31 +76,33 @@ public class SuperGlueHandler {
|
|||
|
||||
RayTraceWorld rayTraceWorld =
|
||||
new RayTraceWorld(world, (p, state) -> p.equals(pos) ? Blocks.AIR.defaultBlockState() : state);
|
||||
BlockHitResult ray = rayTraceWorld.clip(
|
||||
new ClipContext(start, end, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, placer));
|
||||
BlockHitResult ray =
|
||||
rayTraceWorld.clip(new ClipContext(start, end, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, placer));
|
||||
|
||||
Direction face = ray.getDirection();
|
||||
if (face == null || ray.getType() == Type.MISS)
|
||||
return;
|
||||
|
||||
if (!ray.getBlockPos()
|
||||
.relative(face)
|
||||
BlockPos gluePos = ray.getBlockPos();
|
||||
if (!gluePos.relative(face)
|
||||
.equals(pos)) {
|
||||
event.setCanceled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
SuperGlueEntity entity = new SuperGlueEntity(world, ray.getBlockPos(), face.getOpposite());
|
||||
if (SuperGlueEntity.isGlued(world, gluePos, face, null))
|
||||
return;
|
||||
|
||||
SuperGlueEntity entity = new SuperGlueEntity(world, SuperGlueEntity.span(gluePos, gluePos.relative(face)));
|
||||
CompoundTag compoundnbt = itemstack.getTag();
|
||||
if (compoundnbt != null)
|
||||
EntityType.updateCustomEntityTag(world, placer, entity, compoundnbt);
|
||||
|
||||
if (entity.onValidSurface()) {
|
||||
if (SuperGlueEntity.isValidFace(world, gluePos, face)) {
|
||||
if (!world.isClientSide) {
|
||||
entity.playPlaceSound();
|
||||
world.addFreshEntity(entity);
|
||||
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> entity),
|
||||
new GlueEffectPacket(ray.getBlockPos(), face, true));
|
||||
new GlueEffectPacket(gluePos, face, true));
|
||||
}
|
||||
itemstack.hurtAndBreak(1, placer, SuperGlueItem::onBroken);
|
||||
}
|
||||
|
|
|
@ -7,15 +7,11 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.particles.ItemParticleOption;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
@ -49,47 +45,17 @@ public class SuperGlueItem extends Item {
|
|||
super(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAttackBlock(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeDepleted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useOn(UseOnContext context) {
|
||||
BlockPos blockpos = context.getClickedPos();
|
||||
Direction direction = context.getClickedFace();
|
||||
BlockPos blockpos1 = blockpos.relative(direction);
|
||||
Player playerentity = context.getPlayer();
|
||||
ItemStack itemstack = context.getItemInHand();
|
||||
|
||||
if (playerentity == null || !this.canPlace(playerentity, direction, itemstack, blockpos1))
|
||||
return InteractionResult.FAIL;
|
||||
|
||||
Level world = context.getLevel();
|
||||
SuperGlueEntity entity = new SuperGlueEntity(world, blockpos1, direction);
|
||||
CompoundTag compoundnbt = itemstack.getTag();
|
||||
if (compoundnbt != null)
|
||||
EntityType.updateCustomEntityTag(world, playerentity, entity, compoundnbt);
|
||||
|
||||
if (!entity.onValidSurface())
|
||||
return InteractionResult.FAIL;
|
||||
|
||||
if (!world.isClientSide) {
|
||||
entity.playPlaceSound();
|
||||
world.addFreshEntity(entity);
|
||||
}
|
||||
itemstack.hurtAndBreak(1, playerentity, SuperGlueItem::onBroken);
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
public static void onBroken(Player player) {
|
||||
|
||||
}
|
||||
|
||||
protected boolean canPlace(Player entity, Direction facing, ItemStack stack, BlockPos pos) {
|
||||
return !entity.level.isOutsideBuildHeight(pos) && entity.mayUseItemAt(pos, facing, stack);
|
||||
}
|
||||
public static void onBroken(Player player) {}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static void spawnParticles(Level world, BlockPos pos, Direction direction, boolean fullBlock) {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraftforge.network.NetworkEvent.Context;
|
||||
|
||||
public class SuperGlueRemovalPacket extends SimplePacketBase {
|
||||
|
||||
private int entityId;
|
||||
private BlockPos soundSource;
|
||||
|
||||
public SuperGlueRemovalPacket(int id, BlockPos soundSource) {
|
||||
entityId = id;
|
||||
this.soundSource = soundSource;
|
||||
}
|
||||
|
||||
public SuperGlueRemovalPacket(FriendlyByteBuf buffer) {
|
||||
entityId = buffer.readInt();
|
||||
soundSource = buffer.readBlockPos();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(entityId);
|
||||
buffer.writeBlockPos(soundSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Supplier<Context> context) {
|
||||
Context ctx = context.get();
|
||||
ctx.enqueueWork(() -> {
|
||||
ServerPlayer player = ctx.getSender();
|
||||
Entity entity = player.level.getEntity(entityId);
|
||||
if (!(entity instanceof SuperGlueEntity superGlue))
|
||||
return;
|
||||
double range = 32;
|
||||
if (player.distanceToSqr(superGlue.position()) > range * range)
|
||||
return;
|
||||
AllSoundEvents.SLIME_ADDED.play(player.level, null, soundSource, 0.5F, 0.5F);
|
||||
superGlue.spawnParticles();
|
||||
entity.discard();
|
||||
});
|
||||
ctx.setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,146 +1,27 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
|
||||
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack.Pose;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class SuperGlueRenderer extends EntityRenderer<SuperGlueEntity> {
|
||||
|
||||
private ResourceLocation regular = Create.asResource("textures/entity/super_glue/slime.png");
|
||||
|
||||
private float[] insideQuad;
|
||||
private float[] outsideQuad;
|
||||
|
||||
public SuperGlueRenderer(EntityRendererProvider.Context context) {
|
||||
super(context);
|
||||
initQuads();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureLocation(SuperGlueEntity entity) {
|
||||
return regular;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRender(SuperGlueEntity entity, Frustum frustum, double x, double y, double z) {
|
||||
if (super.shouldRender(entity, frustum, x, y, z)) {
|
||||
Player player = Minecraft.getInstance().player;
|
||||
boolean visible = entity.isVisible();
|
||||
boolean holdingGlue = AllItems.SUPER_GLUE.isIn(player.getMainHandItem())
|
||||
|| AllItems.SUPER_GLUE.isIn(player.getOffhandItem());
|
||||
|
||||
if (visible || holdingGlue)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(SuperGlueEntity entity, float yaw, float partialTicks, PoseStack ms,
|
||||
MultiBufferSource buffer, int light) {
|
||||
super.render(entity, yaw, partialTicks, ms, buffer, light);
|
||||
|
||||
VertexConsumer builder = buffer.getBuffer(RenderType.entityCutout(getTextureLocation(entity)));
|
||||
light = getBrightnessForRender(entity);
|
||||
Direction face = entity.getFacingDirection();
|
||||
|
||||
ms.pushPose();
|
||||
TransformStack.cast(ms)
|
||||
.rotateY(AngleHelper.horizontalAngle(face))
|
||||
.rotateX(AngleHelper.verticalAngle(face));
|
||||
Pose peek = ms.last();
|
||||
|
||||
renderQuad(builder, peek, insideQuad, light, -1);
|
||||
renderQuad(builder, peek, outsideQuad, light, 1);
|
||||
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
private void initQuads() {
|
||||
Vec3 diff = Vec3.atLowerCornerOf(Direction.SOUTH.getNormal());
|
||||
Vec3 extension = diff.normalize()
|
||||
.scale(1 / 32f - 1 / 128f);
|
||||
|
||||
Vec3 plane = VecHelper.axisAlingedPlaneOf(diff);
|
||||
Axis axis = Direction.getNearest(diff.x, diff.y, diff.z)
|
||||
.getAxis();
|
||||
|
||||
Vec3 start = Vec3.ZERO.subtract(extension);
|
||||
Vec3 end = Vec3.ZERO.add(extension);
|
||||
|
||||
plane = plane.scale(1 / 2f);
|
||||
Vec3 a1 = plane.add(start);
|
||||
Vec3 b1 = plane.add(end);
|
||||
plane = VecHelper.rotate(plane, -90, axis);
|
||||
Vec3 a2 = plane.add(start);
|
||||
Vec3 b2 = plane.add(end);
|
||||
plane = VecHelper.rotate(plane, -90, axis);
|
||||
Vec3 a3 = plane.add(start);
|
||||
Vec3 b3 = plane.add(end);
|
||||
plane = VecHelper.rotate(plane, -90, axis);
|
||||
Vec3 a4 = plane.add(start);
|
||||
Vec3 b4 = plane.add(end);
|
||||
|
||||
insideQuad = new float[] {
|
||||
(float) a1.x, (float) a1.y, (float) a1.z, 1, 0,
|
||||
(float) a2.x, (float) a2.y, (float) a2.z, 1, 1,
|
||||
(float) a3.x, (float) a3.y, (float) a3.z, 0, 1,
|
||||
(float) a4.x, (float) a4.y, (float) a4.z, 0, 0,
|
||||
};
|
||||
outsideQuad = new float[] {
|
||||
(float) b4.x, (float) b4.y, (float) b4.z, 0, 0,
|
||||
(float) b3.x, (float) b3.y, (float) b3.z, 0, 1,
|
||||
(float) b2.x, (float) b2.y, (float) b2.z, 1, 1,
|
||||
(float) b1.x, (float) b1.y, (float) b1.z, 1, 0,
|
||||
};
|
||||
}
|
||||
|
||||
private int getBrightnessForRender(SuperGlueEntity entity) {
|
||||
BlockPos blockpos = entity.getHangingPosition();
|
||||
BlockPos blockpos2 = blockpos.relative(entity.getFacingDirection()
|
||||
.getOpposite());
|
||||
|
||||
Level world = entity.getCommandSenderWorld();
|
||||
int light = world.isLoaded(blockpos) ? LevelRenderer.getLightColor(world, blockpos) : 15;
|
||||
int light2 = world.isLoaded(blockpos2) ? LevelRenderer.getLightColor(world, blockpos2) : 15;
|
||||
return Math.max(light, light2);
|
||||
}
|
||||
|
||||
// Vertex format: pos x, pos y, pos z, u, v
|
||||
private void renderQuad(VertexConsumer builder, Pose matrix, float[] data, int light, float normalZ) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
builder.vertex(matrix.pose(), data[5 * i], data[5 * i + 1], data[5 * i + 2])
|
||||
.color(255, 255, 255, 255)
|
||||
.uv(data[5 * i + 3], data[5 * i + 4])
|
||||
.overlayCoords(OverlayTexture.NO_OVERLAY)
|
||||
.uv2(light)
|
||||
.normal(matrix.normal(), 0.0f, 0.0f, normalZ)
|
||||
.endVertex();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,42 +1,53 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.AllSpecialTextures;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
import com.simibubi.create.foundation.utility.outliner.Outline.OutlineParams;
|
||||
import com.simibubi.create.foundation.utility.RaycastHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.HitResult.Type;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
|
||||
public class SuperGlueSelectionHandler {
|
||||
|
||||
private static final int SUCCESS = 0x68c586;
|
||||
private static final int PASSIVE = 0x4D9162;
|
||||
private static final int HIGHLIGHT = 0x68c586;
|
||||
private static final int FAIL = 0xc5b548;
|
||||
|
||||
private Object clusterOutlineSlot = new Object();
|
||||
private Object bbOutlineSlot = new Object();
|
||||
private int clusterCooldown;
|
||||
|
||||
private BlockPos firstPos;
|
||||
private BlockPos hoveredPos;
|
||||
private Set<BlockPos> currentCluster;
|
||||
private int glueRequired;
|
||||
|
||||
private SuperGlueEntity selected;
|
||||
private BlockPos soundSourceForRemoval;
|
||||
|
||||
public void tick() {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
LocalPlayer player = mc.player;
|
||||
|
@ -49,6 +60,51 @@ public class SuperGlueSelectionHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
if (clusterCooldown > 0) {
|
||||
if (clusterCooldown == 25)
|
||||
player.displayClientMessage(TextComponent.EMPTY, true);
|
||||
CreateClient.OUTLINER.keep(clusterOutlineSlot);
|
||||
clusterCooldown--;
|
||||
}
|
||||
|
||||
AABB scanArea = player.getBoundingBox()
|
||||
.inflate(32, 16, 32);
|
||||
|
||||
List<SuperGlueEntity> glueNearby = mc.level.getEntitiesOfClass(SuperGlueEntity.class, scanArea);
|
||||
|
||||
selected = null;
|
||||
if (firstPos == null) {
|
||||
double range = player.getAttribute(ForgeMod.REACH_DISTANCE.get())
|
||||
.getValue() + 1;
|
||||
Vec3 traceOrigin = RaycastHelper.getTraceOrigin(player);
|
||||
Vec3 traceTarget = RaycastHelper.getTraceTarget(player, range, traceOrigin);
|
||||
|
||||
double bestDistance = Double.MAX_VALUE;
|
||||
for (SuperGlueEntity glueEntity : glueNearby) {
|
||||
Optional<Vec3> clip = glueEntity.getBoundingBox()
|
||||
.clip(traceOrigin, traceTarget);
|
||||
if (clip.isEmpty())
|
||||
continue;
|
||||
Vec3 vec3 = clip.get();
|
||||
double distanceToSqr = vec3.distanceToSqr(traceOrigin);
|
||||
if (distanceToSqr > bestDistance)
|
||||
continue;
|
||||
selected = glueEntity;
|
||||
soundSourceForRemoval = new BlockPos(vec3);
|
||||
bestDistance = distanceToSqr;
|
||||
}
|
||||
|
||||
for (SuperGlueEntity glueEntity : glueNearby) {
|
||||
boolean h = clusterCooldown == 0 && glueEntity == selected;
|
||||
AllSpecialTextures faceTex = h ? AllSpecialTextures.GLUE : null;
|
||||
CreateClient.OUTLINER.showAABB(glueEntity, glueEntity.getBoundingBox())
|
||||
.colored(h ? HIGHLIGHT : PASSIVE)
|
||||
.withFaceTextures(faceTex, faceTex)
|
||||
.disableNormals()
|
||||
.lineWidth(h ? 1 / 16f : 1 / 64f);
|
||||
}
|
||||
}
|
||||
|
||||
HitResult hitResult = mc.hitResult;
|
||||
if (hitResult != null && hitResult.getType() == Type.BLOCK)
|
||||
hovered = ((BlockHitResult) hitResult).getBlockPos();
|
||||
|
@ -83,33 +139,29 @@ public class SuperGlueSelectionHandler {
|
|||
else if (cancel)
|
||||
Lang.sendStatus(player, FAIL, "super_glue.click_to_discard");
|
||||
else
|
||||
Lang.sendStatus(player, SUCCESS, "super_glue.click_to_confirm");
|
||||
Lang.sendStatus(player, HIGHLIGHT, "super_glue.click_to_confirm");
|
||||
|
||||
if (currentSelectionBox != null)
|
||||
CreateClient.OUTLINER.showAABB(bbOutlineSlot, currentSelectionBox)
|
||||
.colored(canReach && canAfford && !cancel ? HIGHLIGHT : FAIL)
|
||||
.withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.GLUE)
|
||||
.disableNormals()
|
||||
.lineWidth(1 / 16f);
|
||||
|
||||
CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster)
|
||||
.colored(canReach && canAfford && !cancel ? SUCCESS : FAIL)
|
||||
.withFaceTextures(AllSpecialTextures.CHECKERED, AllSpecialTextures.HIGHLIGHT_CHECKERED)
|
||||
.lineWidth(1 / 16f);
|
||||
}
|
||||
if (currentSelectionBox != null) {
|
||||
OutlineParams params =
|
||||
firstPos == null ? CreateClient.OUTLINER.showAABB(bbOutlineSlot, currentSelectionBox)
|
||||
: CreateClient.OUTLINER.chaseAABB(bbOutlineSlot, currentSelectionBox);
|
||||
params.colored(0x111111)
|
||||
.colored(0x4D9162)
|
||||
.disableNormals()
|
||||
.lineWidth(1 / 128f);
|
||||
.lineWidth(1 / 64f);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
hoveredPos = hovered;
|
||||
|
||||
Pair<Set<BlockPos>, List<BlockFace>> pair =
|
||||
SuperGlueSelectionHelper.searchGlueGroup(mc.level, firstPos, hoveredPos);
|
||||
|
||||
currentCluster = pair == null ? null : pair.getFirst();
|
||||
glueRequired = pair == null ? 0
|
||||
: pair.getSecond()
|
||||
.size();
|
||||
Set<BlockPos> cluster = SuperGlueSelectionHelper.searchGlueGroup(mc.level, firstPos, hoveredPos, true);
|
||||
currentCluster = cluster;
|
||||
glueRequired = 1;
|
||||
}
|
||||
|
||||
private boolean isGlue(ItemStack stack) {
|
||||
|
@ -120,7 +172,7 @@ public class SuperGlueSelectionHandler {
|
|||
return firstPos == null || hoveredPos == null ? null : new AABB(firstPos, hoveredPos).expandTowards(1, 1, 1);
|
||||
}
|
||||
|
||||
public boolean onMouseInput() {
|
||||
public boolean onMouseInput(boolean attack) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
LocalPlayer player = mc.player;
|
||||
ClientLevel level = mc.level;
|
||||
|
@ -128,6 +180,15 @@ public class SuperGlueSelectionHandler {
|
|||
if (!isGlue(player.getMainHandItem()))
|
||||
return false;
|
||||
|
||||
if (attack) {
|
||||
if (selected == null)
|
||||
return false;
|
||||
AllPackets.channel.sendToServer(new SuperGlueRemovalPacket(selected.getId(), soundSourceForRemoval));
|
||||
selected = null;
|
||||
clusterCooldown = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.isSteppingCarefully()) {
|
||||
if (firstPos != null) {
|
||||
discard();
|
||||
|
@ -139,7 +200,9 @@ public class SuperGlueSelectionHandler {
|
|||
if (hoveredPos == null)
|
||||
return false;
|
||||
|
||||
Direction face = null;
|
||||
if (mc.hitResult instanceof BlockHitResult bhr) {
|
||||
face = bhr.getDirection();
|
||||
BlockState blockState = level.getBlockState(hoveredPos);
|
||||
if (blockState.getBlock()instanceof AbstractChassisBlock cb)
|
||||
if (cb.getGlueableSide(blockState, bhr.getDirection()) != null)
|
||||
|
@ -158,7 +221,11 @@ public class SuperGlueSelectionHandler {
|
|||
}
|
||||
|
||||
firstPos = hoveredPos;
|
||||
if (face != null)
|
||||
SuperGlueItem.spawnParticles(level, firstPos, face, true);
|
||||
Lang.sendStatus(player, "super_glue.first_pos");
|
||||
AllSoundEvents.SLIME_ADDED.playAt(level, firstPos, 0.5F, 0.85F, false);
|
||||
level.playSound(player, firstPos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 0.75f, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -167,13 +234,25 @@ public class SuperGlueSelectionHandler {
|
|||
currentCluster = null;
|
||||
firstPos = null;
|
||||
Lang.sendStatus(player, "super_glue.abort");
|
||||
clusterCooldown = 0;
|
||||
}
|
||||
|
||||
public void confirm() {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
AllPackets.channel.sendToServer(new SuperGlueSelectionPacket(firstPos, hoveredPos));
|
||||
AllSoundEvents.SLIME_ADDED.playAt(player.level, hoveredPos, 0.5F, 0.95F, false);
|
||||
player.level.playSound(player, hoveredPos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 0.75f, 1);
|
||||
|
||||
if (currentCluster != null)
|
||||
CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster)
|
||||
.colored(0xB5F2C6)
|
||||
.withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.HIGHLIGHT_CHECKERED)
|
||||
.disableNormals()
|
||||
.lineWidth(1 / 24f);
|
||||
|
||||
discard();
|
||||
Lang.sendStatus(player, "super_glue.sucess");
|
||||
clusterCooldown = 40;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,13 +3,10 @@ package com.simibubi.create.content.contraptions.components.structureMovement.gl
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
|
@ -22,17 +19,16 @@ import net.minecraft.world.phys.Vec3;
|
|||
|
||||
public class SuperGlueSelectionHelper {
|
||||
|
||||
public static Pair<Set<BlockPos>, List<BlockFace>> searchGlueGroup(Level level, BlockPos startPos,
|
||||
BlockPos endPos) {
|
||||
public static Set<BlockPos> searchGlueGroup(Level level, BlockPos startPos, BlockPos endPos, boolean includeOther) {
|
||||
if (endPos == null || startPos == null)
|
||||
return null;
|
||||
|
||||
AABB bb = new AABB(startPos, endPos).expandTowards(1, 1, 1);
|
||||
AABB bb = SuperGlueEntity.span(startPos, endPos);
|
||||
|
||||
List<BlockPos> frontier = new ArrayList<>();
|
||||
Set<BlockPos> visited = new HashSet<>();
|
||||
Set<BlockPos> attached = new HashSet<>();
|
||||
List<BlockFace> glue = new ArrayList<>();
|
||||
Set<SuperGlueEntity> cachedOther = new HashSet<>();
|
||||
|
||||
visited.add(startPos);
|
||||
frontier.add(startPos);
|
||||
|
@ -41,11 +37,10 @@ public class SuperGlueSelectionHelper {
|
|||
BlockPos currentPos = frontier.remove(0);
|
||||
attached.add(currentPos);
|
||||
|
||||
Map<Direction, SuperGlueEntity> gatheredGlue = SuperGlueHandler.gatherGlue(level, currentPos);
|
||||
for (Direction d : Iterate.directions) {
|
||||
BlockPos offset = currentPos.relative(d);
|
||||
boolean gluePresent = gatheredGlue.containsKey(d);
|
||||
boolean alreadySticky = SuperGlueEntity.isSideSticky(level, currentPos, d)
|
||||
boolean gluePresent = includeOther && SuperGlueEntity.isGlued(level, currentPos, d, cachedOther);
|
||||
boolean alreadySticky = includeOther && SuperGlueEntity.isSideSticky(level, currentPos, d)
|
||||
|| SuperGlueEntity.isSideSticky(level, offset, d.getOpposite());
|
||||
|
||||
if (!alreadySticky && !gluePresent && !bb.contains(Vec3.atCenterOf(offset)))
|
||||
|
@ -56,20 +51,15 @@ public class SuperGlueSelectionHelper {
|
|||
|| !SuperGlueEntity.isValidFace(level, offset, d.getOpposite()))
|
||||
continue;
|
||||
|
||||
boolean glueNecessary = !gluePresent && !alreadySticky;
|
||||
|
||||
if (visited.add(offset)) {
|
||||
if (visited.add(offset))
|
||||
frontier.add(offset);
|
||||
if (glueNecessary)
|
||||
glue.add(new BlockFace(offset, d));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (attached.size() < 2 && attached.contains(endPos))
|
||||
return null;
|
||||
|
||||
return Pair.of(attached, glue);
|
||||
return attached;
|
||||
}
|
||||
|
||||
public static boolean collectGlueFromInventory(Player player, int requiredAmount, boolean simulate) {
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
import net.minecraftforge.network.NetworkEvent.Context;
|
||||
|
@ -50,19 +47,19 @@ public class SuperGlueSelectionPacket extends SimplePacketBase {
|
|||
if (!to.closerThan(from, 25))
|
||||
return;
|
||||
|
||||
Pair<Set<BlockPos>, List<BlockFace>> group =
|
||||
SuperGlueSelectionHelper.searchGlueGroup(player.level, from, to);
|
||||
Set<BlockPos> group = SuperGlueSelectionHelper.searchGlueGroup(player.level, from, to, false);
|
||||
if (group == null)
|
||||
return;
|
||||
if (!group.getFirst()
|
||||
.contains(to))
|
||||
if (!group.contains(to))
|
||||
return;
|
||||
List<BlockFace> glue = group.getSecond();
|
||||
if (!SuperGlueSelectionHelper.collectGlueFromInventory(player, glue.size(), true))
|
||||
if (!SuperGlueSelectionHelper.collectGlueFromInventory(player, 1, true))
|
||||
return;
|
||||
|
||||
SuperGlueSelectionHelper.collectGlueFromInventory(player, glue.size(), false);
|
||||
Create.GLUE_QUEUE.add(player.level, glue);
|
||||
|
||||
AABB bb = SuperGlueEntity.span(from, to);
|
||||
SuperGlueSelectionHelper.collectGlueFromInventory(player, 1, false);
|
||||
SuperGlueEntity entity = new SuperGlueEntity(player.level, bb);
|
||||
player.level.addFreshEntity(entity);
|
||||
entity.spawnParticles();
|
||||
});
|
||||
ctx.setPacketHandled(true);
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||
package com.simibubi.create.content.contraptions.components.structureMovement.glue;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
|
@ -122,7 +122,6 @@ public class CommonEvents {
|
|||
LinkedControllerServerHandler.tick(world);
|
||||
ControlsServerHandler.tick(world);
|
||||
Create.RAILWAYS.tick(world);
|
||||
Create.GLUE_QUEUE.tick(world);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.simibubi.create.content.logistics.trains.track.CurvedTrackInteraction
|
|||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringHandler;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueHandler;
|
||||
|
||||
import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.InputEvent.ClickInputEvent;
|
||||
|
@ -68,12 +69,14 @@ public class InputEvents {
|
|||
return;
|
||||
}
|
||||
|
||||
if (event.getKeyMapping() == mc.options.keyUse) {
|
||||
if (CreateClient.GLUE_HANDLER.onMouseInput())
|
||||
KeyMapping key = event.getKeyMapping();
|
||||
|
||||
if (key == mc.options.keyUse || key == mc.options.keyAttack) {
|
||||
if (CreateClient.GLUE_HANDLER.onMouseInput(key == mc.options.keyAttack))
|
||||
event.setCanceled(true);
|
||||
}
|
||||
|
||||
if (event.getKeyMapping() == mc.options.keyPickItem) {
|
||||
if (key == mc.options.keyPickItem) {
|
||||
if (ToolboxHandlerClient.onPickItem())
|
||||
event.setCanceled(true);
|
||||
return;
|
||||
|
|
|
@ -92,19 +92,19 @@ public class CloneCommand {
|
|||
List<SuperGlueEntity> glue = world.getEntitiesOfClass(SuperGlueEntity.class, AABB.of(sourceArea));
|
||||
List<Pair<BlockPos, Direction>> newGlue = Lists.newArrayList();
|
||||
|
||||
for (SuperGlueEntity g : glue) {
|
||||
BlockPos pos = g.getHangingPosition();
|
||||
Direction direction = g.getFacingDirection();
|
||||
newGlue.add(Pair.of(pos.offset(diffToTarget), direction));
|
||||
}
|
||||
|
||||
for (Pair<BlockPos, Direction> p : newGlue) {
|
||||
SuperGlueEntity g = new SuperGlueEntity(world, p.getFirst(), p.getSecond());
|
||||
if (g.onValidSurface()) {
|
||||
world.addFreshEntity(g);
|
||||
gluePastes++;
|
||||
}
|
||||
}
|
||||
// for (SuperGlueEntity g : glue) {TODO
|
||||
// BlockPos pos = g.getHangingPosition();
|
||||
// Direction direction = g.getFacingDirection();
|
||||
// newGlue.add(Pair.of(pos.offset(diffToTarget), direction));
|
||||
// }
|
||||
//
|
||||
// for (Pair<BlockPos, Direction> p : newGlue) {
|
||||
// SuperGlueEntity g = new SuperGlueEntity(world, p.getFirst(), p.getSecond());
|
||||
// if (g.onValidSurface()) {
|
||||
// world.addFreshEntity(g);
|
||||
// gluePastes++;
|
||||
// }
|
||||
// }
|
||||
return gluePastes;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,26 +7,26 @@ import net.minecraft.commands.CommandSourceStack;
|
|||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
|
||||
public class GlueCommand {
|
||||
public static ArgumentBuilder<CommandSourceStack, ?> register() {
|
||||
return Commands.literal("glue")
|
||||
.requires(cs -> cs.hasPermission(2))
|
||||
.then(Commands.argument("pos", BlockPosArgument.blockPos())
|
||||
//.then(Commands.argument("direction", EnumArgument.enumArgument(Direction.class))
|
||||
.executes(ctx -> {
|
||||
BlockPos pos = BlockPosArgument.getLoadedBlockPos(ctx, "pos");
|
||||
.requires(cs -> cs.hasPermission(2))
|
||||
.then(Commands.argument("from", BlockPosArgument.blockPos())
|
||||
.then(Commands.argument("to", BlockPosArgument.blockPos())
|
||||
.executes(ctx -> {
|
||||
BlockPos from = BlockPosArgument.getLoadedBlockPos(ctx, "from");
|
||||
BlockPos to = BlockPosArgument.getLoadedBlockPos(ctx, "to");
|
||||
|
||||
ServerLevel world = ctx.getSource().getLevel();
|
||||
SuperGlueEntity entity = new SuperGlueEntity(world, pos, Direction.UP);
|
||||
ServerLevel world = ctx.getSource()
|
||||
.getLevel();
|
||||
|
||||
entity.playPlaceSound();
|
||||
world.addFreshEntity(entity);
|
||||
|
||||
return 1;
|
||||
}));
|
||||
SuperGlueEntity entity = new SuperGlueEntity(world, SuperGlueEntity.span(from, to));
|
||||
entity.playPlaceSound();
|
||||
world.addFreshEntity(entity);
|
||||
return 1;
|
||||
})));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraptionUpdatePacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueEffectPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueRemovalPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueSelectionPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsInputPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsStopControllingPacket;
|
||||
|
@ -130,6 +131,7 @@ public enum AllPackets {
|
|||
SELECT_CURVED_TRACK(CurvedTrackSelectionPacket.class, CurvedTrackSelectionPacket::new, PLAY_TO_SERVER),
|
||||
PLACE_CURVED_TRACK(PlaceExtendedCurvePacket.class, PlaceExtendedCurvePacket::new, PLAY_TO_SERVER),
|
||||
GLUE_IN_AREA(SuperGlueSelectionPacket.class, SuperGlueSelectionPacket::new, PLAY_TO_SERVER),
|
||||
GLUE_REMOVED(SuperGlueRemovalPacket.class, SuperGlueRemovalPacket::new, PLAY_TO_SERVER),
|
||||
|
||||
// Server to Client
|
||||
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
|
||||
|
|
|
@ -13,7 +13,6 @@ import com.simibubi.create.content.contraptions.base.KineticBlock;
|
|||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.content.contraptions.components.crafter.ConnectedInputHandler;
|
||||
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueItem;
|
||||
import com.simibubi.create.content.contraptions.fluids.PumpTileEntity;
|
||||
import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData;
|
||||
|
@ -661,11 +660,6 @@ public class SceneBuilder {
|
|||
});
|
||||
}
|
||||
|
||||
public ElementLink<EntityElement> createGlueEntity(BlockPos pos, Direction face) {
|
||||
effects.superGlue(pos, face, false);
|
||||
return createEntity(world -> new SuperGlueEntity(world, pos, face.getOpposite()));
|
||||
}
|
||||
|
||||
public void createItemOnBeltLike(BlockPos location, Direction insertionSide, ItemStack stack) {
|
||||
addInstruction(scene -> {
|
||||
PonderWorld world = scene.getWorld();
|
||||
|
|
|
@ -253,7 +253,7 @@ public class ChassisScenes {
|
|||
scene.overlay.showControls(new InputWindowElement(glueSurface, Pointing.DOWN).rightClick()
|
||||
.withItem(AllItems.SUPER_GLUE.asStack()), 30);
|
||||
scene.idle(7);
|
||||
ElementLink<EntityElement> glueEntity = scene.world.createGlueEntity(chassisPos.west(), Direction.NORTH);
|
||||
// ElementLink<EntityElement> glueEntity = scene.world.createGlueEntity(chassisPos.west(), Direction.NORTH);TODO
|
||||
scene.idle(20);
|
||||
ElementLink<WorldSectionElement> gluedPlank =
|
||||
scene.world.showIndependentSection(util.select.position(3, 3, 1), Direction.SOUTH);
|
||||
|
@ -262,7 +262,7 @@ public class ChassisScenes {
|
|||
scene.effects.superGlue(chassisPos.west(), Direction.NORTH, true);
|
||||
scene.idle(20);
|
||||
|
||||
scene.world.modifyEntity(glueEntity, Entity::discard);
|
||||
// scene.world.modifyEntity(glueEntity, Entity::discard);
|
||||
scene.world.hideIndependentSection(glassSection, Direction.UP);
|
||||
scene.world.hideIndependentSection(gluedPlank, Direction.UP);
|
||||
scene.world.hideIndependentSection(topGlassSection, Direction.UP);
|
||||
|
@ -499,7 +499,7 @@ public class ChassisScenes {
|
|||
scene.overlay.showControls(new InputWindowElement(blockSurface, Pointing.DOWN).rightClick()
|
||||
.withItem(AllItems.SUPER_GLUE.asStack()), 40);
|
||||
scene.idle(7);
|
||||
ElementLink<EntityElement> glueEntity = scene.world.createGlueEntity(central, Direction.NORTH);
|
||||
// ElementLink<EntityElement> glueEntity = scene.world.createGlueEntity(central, Direction.NORTH);TODO
|
||||
scene.idle(10);
|
||||
scene.overlay.showText(60)
|
||||
.pointAt(blockSurface)
|
||||
|
@ -510,7 +510,7 @@ public class ChassisScenes {
|
|||
|
||||
scene.world.glueBlockOnto(central.north(), Direction.SOUTH, plank);
|
||||
scene.idle(20);
|
||||
scene.world.modifyEntity(glueEntity, Entity::discard);
|
||||
// scene.world.modifyEntity(glueEntity, Entity::discard);
|
||||
|
||||
BlockPos bearingPos = util.grid.at(2, 1, 2);
|
||||
scene.world.configureCenterOfRotation(plank, util.vector.centerOf(bearingPos));
|
||||
|
@ -553,13 +553,13 @@ public class ChassisScenes {
|
|||
scene.world.rotateSection(plank, 0, 360, 0, 80);
|
||||
scene.idle(90);
|
||||
|
||||
glueEntity = scene.world.createGlueEntity(central, Direction.UP);
|
||||
// glueEntity = scene.world.createGlueEntity(central, Direction.UP);TODO
|
||||
scene.world.destroyBlock(central.above());
|
||||
scene.idle(20);
|
||||
scene.addKeyframe();
|
||||
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(central), Pointing.DOWN).leftClick(), 40);
|
||||
scene.idle(7);
|
||||
scene.world.modifyEntity(glueEntity, Entity::discard);
|
||||
// scene.world.modifyEntity(glueEntity, Entity::discard);
|
||||
scene.effects.superGlue(central, Direction.UP, false);
|
||||
scene.idle(10);
|
||||
scene.overlay.showText(60)
|
||||
|
|
|
@ -55,27 +55,47 @@ public class BlockClusterOutline extends Outline {
|
|||
});
|
||||
}
|
||||
|
||||
static Vec3 xyz = new Vec3(-.5, -.5, -.5);
|
||||
static Vec3 Xyz = new Vec3(.5, -.5, -.5);
|
||||
static Vec3 xYz = new Vec3(-.5, .5, -.5);
|
||||
static Vec3 XYz = new Vec3(.5, .5, -.5);
|
||||
static Vec3 xyZ = new Vec3(-.5, -.5, .5);
|
||||
static Vec3 XyZ = new Vec3(.5, -.5, .5);
|
||||
static Vec3 xYZ = new Vec3(-.5, .5, .5);
|
||||
static Vec3 XYZ = new Vec3(.5, .5, .5);
|
||||
|
||||
protected void renderBlockFace(PoseStack ms, VertexConsumer builder, BlockPos pos, Direction face) {
|
||||
Vec3 center = VecHelper.getCenterOf(pos);
|
||||
Vec3 offset = Vec3.atLowerCornerOf(face.getNormal());
|
||||
Vec3 plane = VecHelper.axisAlingedPlaneOf(offset);
|
||||
Axis axis = face.getAxis();
|
||||
offset = offset.scale(1 / 128d);
|
||||
center = center.add(offset);
|
||||
|
||||
offset = offset.scale(1 / 2f + 1 / 128d);
|
||||
plane = plane.scale(1 / 2f)
|
||||
.add(offset);
|
||||
ms.pushPose();
|
||||
ms.translate(center.x, center.y, center.z);
|
||||
|
||||
int deg = face.getAxisDirection()
|
||||
.getStep() * 90;
|
||||
Vec3 a1 = plane.add(center);
|
||||
plane = VecHelper.rotate(plane, deg, axis);
|
||||
Vec3 a2 = plane.add(center);
|
||||
plane = VecHelper.rotate(plane, deg, axis);
|
||||
Vec3 a3 = plane.add(center);
|
||||
plane = VecHelper.rotate(plane, deg, axis);
|
||||
Vec3 a4 = plane.add(center);
|
||||
switch (face) {
|
||||
case DOWN:
|
||||
putQuad(ms, builder, xyz, Xyz, XyZ, xyZ, face);
|
||||
break;
|
||||
case EAST:
|
||||
putQuad(ms, builder, XYz, XYZ, XyZ, Xyz, face);
|
||||
break;
|
||||
case NORTH:
|
||||
putQuad(ms, builder, xYz, XYz, Xyz, xyz, face);
|
||||
break;
|
||||
case SOUTH:
|
||||
putQuad(ms, builder, XYZ, xYZ, xyZ, XyZ, face);
|
||||
break;
|
||||
case UP:
|
||||
putQuad(ms, builder, xYZ, XYZ, XYz, xYz, face);
|
||||
break;
|
||||
case WEST:
|
||||
putQuad(ms, builder, xYZ, xYz, xyz, xyZ, face);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
putQuad(ms, builder, a1, a2, a3, a4, face);
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
private static class Cluster {
|
||||
|
|
BIN
src/main/resources/assets/create/textures/special/glue.png
Normal file
BIN
src/main/resources/assets/create/textures/special/glue.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 275 B |
Loading…
Reference in a new issue