Superglue

- Added superglue, an alternative to chassis blocks
- Added some random safety checks
- Fixed some more bad gl states left by event handlers
This commit is contained in:
simibubi 2020-04-20 23:27:34 +02:00
parent db8e52be2e
commit c62d356f9b
30 changed files with 946 additions and 40 deletions

View file

@ -5,6 +5,8 @@ import java.util.function.Function;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity; import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntityRenderer; import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntityRenderer;
import com.simibubi.create.modules.contraptions.components.contraptions.glue.SuperGlueEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.glue.SuperGlueRenderer;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityClassification; import net.minecraft.entity.EntityClassification;
@ -23,6 +25,8 @@ public enum AllEntities {
ContraptionEntity::build), ContraptionEntity::build),
STATIONARY_CONTRAPTION(ContraptionEntity::new, EntityClassification.MISC, 30, 40, STATIONARY_CONTRAPTION(ContraptionEntity::new, EntityClassification.MISC, 30, 40,
false, ContraptionEntity::build), false, ContraptionEntity::build),
SUPER_GLUE(SuperGlueEntity::new, EntityClassification.MISC, 30, Integer.MAX_VALUE, false, SuperGlueEntity::build),
; ;
private IFactory<?> factory; private IFactory<?> factory;
@ -62,8 +66,8 @@ public enum AllEntities {
@OnlyIn(value = Dist.CLIENT) @OnlyIn(value = Dist.CLIENT)
public static void registerRenderers() { public static void registerRenderers() {
// RenderingRegistry.registerEntityRenderingHandler(CardboardBoxEntity.class, CardboardBoxEntityRenderer::new);
RenderingRegistry.registerEntityRenderingHandler(ContraptionEntity.class, ContraptionEntityRenderer::new); RenderingRegistry.registerEntityRenderingHandler(ContraptionEntity.class, ContraptionEntityRenderer::new);
RenderingRegistry.registerEntityRenderingHandler(SuperGlueEntity.class, SuperGlueRenderer::new);
} }
} }

View file

@ -16,6 +16,7 @@ import com.simibubi.create.foundation.utility.data.ITaggable;
import com.simibubi.create.modules.IModule; import com.simibubi.create.modules.IModule;
import com.simibubi.create.modules.contraptions.GogglesItem; import com.simibubi.create.modules.contraptions.GogglesItem;
import com.simibubi.create.modules.contraptions.WrenchItem; import com.simibubi.create.modules.contraptions.WrenchItem;
import com.simibubi.create.modules.contraptions.components.contraptions.glue.SuperGlueItem;
import com.simibubi.create.modules.contraptions.relays.belt.item.BeltConnectorItem; import com.simibubi.create.modules.contraptions.relays.belt.item.BeltConnectorItem;
import com.simibubi.create.modules.contraptions.relays.gearbox.VerticalGearboxItem; import com.simibubi.create.modules.contraptions.relays.gearbox.VerticalGearboxItem;
import com.simibubi.create.modules.curiosities.ChromaticCompoundCubeItem; import com.simibubi.create.modules.curiosities.ChromaticCompoundCubeItem;
@ -93,8 +94,7 @@ public enum AllItems {
WHISK, WHISK,
BRASS_HAND, BRASS_HAND,
SLOT_COVER, SLOT_COVER,
SUPER_GLUE, SUPER_GLUE(SuperGlueItem::new),
ANTIOXIDANT,
SAND_PAPER(SandPaperItem::new), SAND_PAPER(SandPaperItem::new),
RED_SAND_PAPER(SandPaperItem::new), RED_SAND_PAPER(SandPaperItem::new),
WRENCH(WrenchItem::new), WRENCH(WrenchItem::new),

View file

@ -13,6 +13,7 @@ import com.simibubi.create.foundation.packet.SimplePacketBase;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import com.simibubi.create.modules.contraptions.components.contraptions.CancelPlayerFallPacket; import com.simibubi.create.modules.contraptions.components.contraptions.CancelPlayerFallPacket;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionStallPacket; import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionStallPacket;
import com.simibubi.create.modules.contraptions.components.contraptions.glue.GlueEffectPacket;
import com.simibubi.create.modules.contraptions.relays.advanced.sequencer.ConfigureSequencedGearshiftPacket; import com.simibubi.create.modules.contraptions.relays.advanced.sequencer.ConfigureSequencedGearshiftPacket;
import com.simibubi.create.modules.curiosities.symmetry.SymmetryEffectPacket; import com.simibubi.create.modules.curiosities.symmetry.SymmetryEffectPacket;
import com.simibubi.create.modules.curiosities.zapper.ZapperBeamPacket; import com.simibubi.create.modules.curiosities.zapper.ZapperBeamPacket;
@ -51,6 +52,7 @@ public enum AllPackets {
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new), CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new),
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new), CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new),
TOOL_HARVEST(AbstractToolItem.HarvestPacket.class, AbstractToolItem.HarvestPacket::new), TOOL_HARVEST(AbstractToolItem.HarvestPacket.class, AbstractToolItem.HarvestPacket::new),
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new),
; ;

View file

@ -12,6 +12,8 @@ public class CClient extends ConfigBase {
public ConfigFloat fanParticleDensity = f(.5f, 0, 1, "fanParticleDensity"); public ConfigFloat fanParticleDensity = f(.5f, 0, 1, "fanParticleDensity");
public ConfigBool rainbowDebug = public ConfigBool rainbowDebug =
b(true, "enableRainbowDebug", "Show colourful debug information while the F3-Menu is open."); b(true, "enableRainbowDebug", "Show colourful debug information while the F3-Menu is open.");
public ConfigBool showHiddenSuperGlue =
b(false, "showHiddenSuperGlue", "Show indications for hidden glue between blocks while holding the item.");
@Override @Override
public String getName() { public String getName() {

View file

@ -5,9 +5,9 @@ public class CDamageControl extends ConfigBase {
public ConfigBool freezeCrushing = b(false, "freezeCrushing", Comments.freezeCrushing); public ConfigBool freezeCrushing = b(false, "freezeCrushing", Comments.freezeCrushing);
public ConfigBool freezeExtractors = b(false, "freezeExtractors", Comments.freezeExtractors); public ConfigBool freezeExtractors = b(false, "freezeExtractors", Comments.freezeExtractors);
public ConfigBool freezeInWorldProcessing = b(false, "freezeInWorldProcessing", Comments.freezeInWorldProcessing); public ConfigBool freezeInWorldProcessing = b(false, "freezeInWorldProcessing", Comments.freezeInWorldProcessing);
public ConfigBool freezeRotationPropagator = b(false, "freezeRotationPropagator", Comments.freezeRotationPropagator); public ConfigBool freezeRotationPropagator =
public ConfigBool freezeBearingConstructs = b(false, "freezeBearingConstructs", Comments.freezeBearingConstructs); b(false, "freezeRotationPropagator", Comments.freezeRotationPropagator);
public ConfigBool freezePistonConstructs = b(false, "freezePistonConstructs", Comments.freezePistonConstructs); public ConfigBool freezeContraptions = b(false, "freezeContraptions", Comments.freezeContraptions);
@Override @Override
public String getName() { public String getName() {
@ -20,8 +20,7 @@ public class CDamageControl extends ConfigBase {
static String freezeInWorldProcessing = "In case Encased Fans tried smelting your hardware."; static String freezeInWorldProcessing = "In case Encased Fans tried smelting your hardware.";
static String freezeRotationPropagator = static String freezeRotationPropagator =
"Pauses rotation logic altogether - Use if crash mentions RotationPropagators."; "Pauses rotation logic altogether - Use if crash mentions RotationPropagators.";
static String freezeBearingConstructs = "In case Mechanical Bearings turned against you."; static String freezeContraptions = "In case Moving contraptions pushed it too far.";
static String freezePistonConstructs = "In case Mechanical Pistons pushed it too far.";
} }
} }

View file

@ -71,6 +71,8 @@ public class ValueBoxRenderer {
} }
box.render(highlighted); box.render(highlighted);
GlStateManager.disableBlend();
GlStateManager.disableAlphaTest();
} }
public static void renderText(ValueBox box, FontRenderer font, String text) { public static void renderText(ValueBox box, FontRenderer font, String text) {

View file

@ -60,6 +60,7 @@ public class ScrollValueRenderer {
} }
} else } else
render(world, pos, face, behaviour, highlight); render(world, pos, face, behaviour, highlight);
TessellatorHelper.cleanUpAfterDrawing(); TessellatorHelper.cleanUpAfterDrawing();
GlStateManager.enableAlphaTest(); GlStateManager.enableAlphaTest();
GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);

View file

@ -67,10 +67,9 @@ public class ScreenElementRenderer {
BlockRendererDispatcher blockRenderer = mc.getBlockRendererDispatcher(); BlockRendererDispatcher blockRenderer = mc.getBlockRendererDispatcher();
IBakedModel modelToRender = null; IBakedModel modelToRender = null;
BlockState blockToRender = null; BlockState blockToRender = null;
boolean stateMode = transformsAndModel == null;
boolean fire = false; boolean fire = false;
if (stateMode) { if (transformsAndModel == null) {
blockToRender = transformsAndState.get(); blockToRender = transformsAndState.get();
fire = (blockToRender.getBlock() instanceof FireBlock); fire = (blockToRender.getBlock() instanceof FireBlock);
modelToRender = blockRenderer.getModelForState(blockToRender); modelToRender = blockRenderer.getModelForState(blockToRender);
@ -81,7 +80,6 @@ public class ScreenElementRenderer {
GlStateManager.scaled(50, -50, 50); GlStateManager.scaled(50, -50, 50);
mc.getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); mc.getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
GlStateManager.pushMatrix(); GlStateManager.pushMatrix();
if (fire) { if (fire) {
blockRenderer.renderBlockBrightness(blockToRender, 1); blockRenderer.renderBlockBrightness(blockToRender, 1);
@ -97,7 +95,7 @@ public class ScreenElementRenderer {
} }
GlStateManager.popMatrix(); GlStateManager.popMatrix();
if (stateMode && !blockToRender.getFluidState().isEmpty()) { if (blockToRender != null && !blockToRender.getFluidState().isEmpty()) {
RenderHelper.disableStandardItemLighting(); RenderHelper.disableStandardItemLighting();
Tessellator tessellator = Tessellator.getInstance(); Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer(); BufferBuilder bufferbuilder = tessellator.getBuffer();

View file

@ -10,6 +10,7 @@ import net.minecraft.util.math.BlockPos;
public class Iterate { public class Iterate {
public static final boolean[] trueAndFalse = { true, false }; public static final boolean[] trueAndFalse = { true, false };
public static final int[] zeroAndOne = { 1, -1 };
public static final int[] positiveAndNegative = { 1, -1 }; public static final int[] positiveAndNegative = { 1, -1 };
public static final Direction[] directions = Direction.values(); public static final Direction[] directions = Direction.values();
public static final Direction[] horizontalDirections = getHorizontals(); public static final Direction[] horizontalDirections = getHorizontals();

View file

@ -0,0 +1,37 @@
package com.simibubi.create.foundation.utility;
import java.util.function.BiFunction;
import net.minecraft.block.BlockState;
import net.minecraft.fluid.IFluidState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
public class RayTraceWorld implements IBlockReader {
private IWorld template;
private BiFunction<BlockPos, BlockState, BlockState> stateGetter;
public RayTraceWorld(IWorld template, BiFunction<BlockPos, BlockState, BlockState> stateGetter) {
this.template = template;
this.stateGetter = stateGetter;
}
@Override
public TileEntity getTileEntity(BlockPos pos) {
return template.getTileEntity(pos);
}
@Override
public BlockState getBlockState(BlockPos pos) {
return stateGetter.apply(pos, template.getBlockState(pos));
}
@Override
public IFluidState getFluidState(BlockPos pos) {
return template.getFluidState(pos);
}
}

View file

@ -69,7 +69,6 @@ public class TessellatorHelper {
public static void cleanUpAfterDrawing() { public static void cleanUpAfterDrawing() {
GlStateManager.popAttributes(); GlStateManager.popAttributes();
GlStateManager.popMatrix(); GlStateManager.popMatrix();
GlStateManager.disableAlphaTest();
GlStateManager.disableBlend(); GlStateManager.disableBlend();
} }

View file

@ -25,14 +25,16 @@ import com.simibubi.create.foundation.utility.WrappedWorld;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.glue.SuperGlueEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.glue.SuperGlueHandler;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonHeadBlock; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonHeadBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.PistonPoleBlock; import com.simibubi.create.modules.contraptions.components.contraptions.piston.PistonPoleBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock; import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock.MagnetBlock; import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock.MagnetBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock.RopeBlock; import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock.RopeBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyTileEntity;
import com.simibubi.create.modules.contraptions.components.saw.SawBlock; import com.simibubi.create.modules.contraptions.components.saw.SawBlock;
import com.simibubi.create.modules.contraptions.redstone.ContactBlock; import com.simibubi.create.modules.contraptions.redstone.ContactBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
@ -74,6 +76,7 @@ public abstract class Contraption {
public List<MutablePair<BlockInfo, MovementContext>> actors; public List<MutablePair<BlockInfo, MovementContext>> actors;
public CombinedInvWrapper inventory; public CombinedInvWrapper inventory;
public List<TileEntity> customRenderTEs; public List<TileEntity> customRenderTEs;
public Set<Pair<BlockPos, Direction>> superglue;
public AxisAlignedBB bounds; public AxisAlignedBB bounds;
public boolean stalled; public boolean stalled;
@ -83,13 +86,16 @@ public abstract class Contraption {
protected BlockPos anchor; protected BlockPos anchor;
List<BlockPos> renderOrder; List<BlockPos> renderOrder;
List<SuperGlueEntity> glueToRemove;
public Contraption() { public Contraption() {
blocks = new HashMap<>(); blocks = new HashMap<>();
storage = new HashMap<>(); storage = new HashMap<>();
actors = new ArrayList<>(); actors = new ArrayList<>();
superglue = new HashSet<>();
renderOrder = new ArrayList<>(); renderOrder = new ArrayList<>();
customRenderTEs = new ArrayList<>(); customRenderTEs = new ArrayList<>();
glueToRemove = new ArrayList<>();
} }
public Set<BlockPos> getColliders(World world, Direction movementDirection) { public Set<BlockPos> getColliders(World world, Direction movementDirection) {
@ -242,6 +248,8 @@ public abstract class Contraption {
frontier.add(otherPartPos); frontier.add(otherPartPos);
} }
Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos);
// Slime blocks drag adjacent blocks if possible // Slime blocks drag adjacent blocks if possible
boolean isSlimeBlock = state.getBlock() instanceof SlimeBlock; boolean isSlimeBlock = state.getBlock() instanceof SlimeBlock;
for (Direction offset : Direction.values()) { for (Direction offset : Direction.values()) {
@ -254,9 +262,18 @@ public abstract class Contraption {
return false; return false;
continue; continue;
} }
if (!visited.contains(offsetPos) && ((isSlimeBlock && !BlockMovementTraits.isBrittle(blockState))
|| BlockMovementTraits.isBlockAttachedTowards(blockState, offset.getOpposite()))) boolean wasVisited = visited.contains(offsetPos);
boolean faceHasGlue = superglue.containsKey(offset);
boolean blockAttachedTowardsFace =
BlockMovementTraits.isBlockAttachedTowards(blockState, offset.getOpposite());
boolean brittle = BlockMovementTraits.isBrittle(blockState);
if (!wasVisited && ((isSlimeBlock && !brittle) || blockAttachedTowardsFace || faceHasGlue))
frontier.add(offsetPos); frontier.add(offsetPos);
if (faceHasGlue)
addGlue(superglue.get(offset));
} }
add(pos, capture(world, pos)); add(pos, capture(world, pos));
@ -325,6 +342,14 @@ public abstract class Contraption {
return compoundnbt; return compoundnbt;
} }
public void addGlue(SuperGlueEntity entity) {
BlockPos pos = entity.getHangingPosition();
Direction direction = entity.getFacingDirection();
BlockPos localPos = pos.subtract(anchor);
this.superglue.add(Pair.of(localPos, direction));
glueToRemove.add(entity);
}
public void add(BlockPos pos, Pair<BlockInfo, TileEntity> pair) { public void add(BlockPos pos, Pair<BlockInfo, TileEntity> pair) {
BlockInfo captured = pair.getKey(); BlockInfo captured = pair.getKey();
BlockPos localPos = pos.subtract(anchor); BlockPos localPos = pos.subtract(anchor);
@ -402,6 +427,13 @@ public abstract class Contraption {
getActors().add(MutablePair.of(info, context)); getActors().add(MutablePair.of(info, context));
}); });
superglue.clear();
nbt.getList("Superglue", 10).forEach(c -> {
CompoundNBT comp = (CompoundNBT) c;
superglue.add(Pair.of(NBTUtil.readBlockPos(comp.getCompound("Pos")),
Direction.byIndex(comp.getByte("Direction"))));
});
storage.clear(); storage.clear();
nbt.getList("Storage", 10).forEach(c -> { nbt.getList("Storage", 10).forEach(c -> {
CompoundNBT comp = (CompoundNBT) c; CompoundNBT comp = (CompoundNBT) c;
@ -440,6 +472,14 @@ public abstract class Contraption {
actorsNBT.add(compound); actorsNBT.add(compound);
} }
ListNBT superglueNBT = new ListNBT();
for (Pair<BlockPos, Direction> glueEntry : superglue) {
CompoundNBT c = new CompoundNBT();
c.put("Pos", NBTUtil.writeBlockPos(glueEntry.getKey()));
c.putByte("Direction", (byte) glueEntry.getValue().getIndex());
superglueNBT.add(c);
}
ListNBT storageNBT = new ListNBT(); ListNBT storageNBT = new ListNBT();
for (BlockPos pos : storage.keySet()) { for (BlockPos pos : storage.keySet()) {
CompoundNBT c = new CompoundNBT(); CompoundNBT c = new CompoundNBT();
@ -453,6 +493,7 @@ public abstract class Contraption {
nbt.put("Blocks", blocksNBT); nbt.put("Blocks", blocksNBT);
nbt.put("Actors", actorsNBT); nbt.put("Actors", actorsNBT);
nbt.put("Superglue", superglueNBT);
nbt.put("Storage", storageNBT); nbt.put("Storage", storageNBT);
nbt.put("Anchor", NBTUtil.writeBlockPos(anchor)); nbt.put("Anchor", NBTUtil.writeBlockPos(anchor));
nbt.putBoolean("Stalled", stalled); nbt.putBoolean("Stalled", stalled);
@ -466,11 +507,7 @@ public abstract class Contraption {
} }
public static boolean isFrozen() { public static boolean isFrozen() {
return AllConfigs.SERVER.control.freezePistonConstructs.get(); return AllConfigs.SERVER.control.freezeContraptions.get();
}
public void disassemble(World world, BlockPos offset, Vec3d rotation) {
disassemble(world, offset, rotation, (pos, state) -> false);
} }
public void removeBlocksFromWorld(IWorld world, BlockPos offset) { public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
@ -479,6 +516,8 @@ public abstract class Contraption {
public void removeBlocksFromWorld(IWorld world, BlockPos offset, BiPredicate<BlockPos, BlockState> customRemoval) { public void removeBlocksFromWorld(IWorld world, BlockPos offset, BiPredicate<BlockPos, BlockState> customRemoval) {
storage.values().forEach(MountedStorage::empty); storage.values().forEach(MountedStorage::empty);
glueToRemove.forEach(SuperGlueEntity::remove);
for (boolean brittles : Iterate.trueAndFalse) { for (boolean brittles : Iterate.trueAndFalse) {
for (BlockInfo block : blocks.values()) { for (BlockInfo block : blocks.values()) {
if (brittles != BlockMovementTraits.isBrittle(block.state)) if (brittles != BlockMovementTraits.isBrittle(block.state))
@ -496,7 +535,11 @@ public abstract class Contraption {
} }
} }
public void disassemble(World world, BlockPos offset, Vec3d rotation, public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) {
addBlocksToWorld(world, offset, rotation, (pos, state) -> false);
}
public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation,
BiPredicate<BlockPos, BlockState> customPlacement) { BiPredicate<BlockPos, BlockState> customPlacement) {
stop(world); stop(world);
@ -558,10 +601,21 @@ public abstract class Contraption {
mountedStorage.fill(tileEntity); mountedStorage.fill(tileEntity);
} }
} }
}
}
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.isRemote)
world.addEntity(entity);
} }
} }
} }
public void initActors(World world) { public void initActors(World world) {

View file

@ -427,7 +427,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
if (getContraption() != null) { if (getContraption() != null) {
BlockPos offset = new BlockPos(getPositionVec().add(.5, .5, .5)); BlockPos offset = new BlockPos(getPositionVec().add(.5, .5, .5));
Vec3d rotation = new Vec3d(getRoll(1), getYaw(1), getPitch(1)); Vec3d rotation = new Vec3d(getRoll(1), getYaw(1), getPitch(1));
getContraption().disassemble(world, offset, rotation); getContraption().addBlocksToWorld(world, offset, rotation);
preventMovedEntitiesFromGettingStuck(); preventMovedEntitiesFromGettingStuck();
} }
remove(); remove();

View file

@ -162,14 +162,14 @@ public class StructureTransform {
return state; return state;
} }
protected Axis transformAxis(Axis axisIn) { public Axis transformAxis(Axis axisIn) {
Direction facing = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axisIn); Direction facing = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axisIn);
facing = transformFacing(facing); facing = transformFacing(facing);
Axis axis = facing.getAxis(); Axis axis = facing.getAxis();
return axis; return axis;
} }
protected Direction transformFacing(Direction facing) { public Direction transformFacing(Direction facing) {
for (int i = 0; i < rotation.ordinal(); i++) for (int i = 0; i < rotation.ordinal(); i++)
facing = facing.rotateAround(rotationAxis); facing = facing.rotateAround(rotationAxis);
return facing; return facing;

View file

@ -0,0 +1,49 @@
package com.simibubi.create.modules.contraptions.components.contraptions.glue;
import java.util.function.Supplier;
import com.simibubi.create.foundation.packet.SimplePacketBase;
import net.minecraft.client.Minecraft;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.network.NetworkEvent.Context;
public class GlueEffectPacket extends SimplePacketBase {
private BlockPos pos;
private Direction direction;
private boolean fullBlock;
public GlueEffectPacket(BlockPos pos, Direction direction, boolean fullBlock) {
this.pos = pos;
this.direction = direction;
this.fullBlock = fullBlock;
}
public GlueEffectPacket(PacketBuffer buffer) {
pos = buffer.readBlockPos();
direction = Direction.byIndex(buffer.readByte());
fullBlock = buffer.readBoolean();
}
public void write(PacketBuffer buffer) {
buffer.writeBlockPos(pos);
buffer.writeByte(direction.getIndex());
buffer.writeBoolean(fullBlock);
}
public void handle(Supplier<Context> context) {
context.get().enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
Minecraft mc = Minecraft.getInstance();
if (!mc.player.getPosition().withinDistance(pos, 100))
return;
SuperGlueItem.spawnParticles(mc.world, pos, direction, fullBlock);
}));
context.get().setPacketHandled(true);
}
}

View file

@ -0,0 +1,390 @@
package com.simibubi.create.modules.contraptions.components.contraptions.glue;
import javax.annotation.Nullable;
import org.apache.commons.lang3.Validate;
import com.simibubi.create.AllEntities;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllPackets;
import com.simibubi.create.AllSoundEvents;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntitySize;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.Pose;
import net.minecraft.entity.effect.LightningBoltEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.IPacket;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.fml.network.PacketDistributor;
public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnData {
private int validationTimer;
protected BlockPos hangingPosition;
protected Direction facingDirection = Direction.SOUTH;
public SuperGlueEntity(EntityType<?> type, World world) {
super(type, world);
}
public SuperGlueEntity(World world, BlockPos pos, Direction direction) {
this(AllEntities.SUPER_GLUE.type, world);
hangingPosition = pos;
facingDirection = direction;
updateFacingWithBoundingBox();
}
@Override
protected void registerData() {}
public int getWidthPixels() {
return 12;
}
public int getHeightPixels() {
return 12;
}
public void onBroken(@Nullable Entity breaker) {
playSound(SoundEvents.ENTITY_SLIME_SQUISH_SMALL, 1.0F, 1.0F);
if (onValidSurface()) {
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
new GlueEffectPacket(getHangingPosition(), getFacingDirection().getOpposite(), false));
playSound(AllSoundEvents.SLIME_ADDED.get(), 0.5F, 0.5F);
}
}
public void playPlaceSound() {
playSound(AllSoundEvents.SLIME_ADDED.get(), 0.5F, 0.75F);
}
protected void updateFacingWithBoundingBox() {
Validate.notNull(getFacingDirection());
if (getFacingDirection().getAxis().isHorizontal()) {
this.rotationPitch = 0.0F;
this.rotationYaw = getFacingDirection().getHorizontalIndex() * 90;
} else {
this.rotationPitch = -90 * getFacingDirection().getAxisDirection().getOffset();
this.rotationYaw = 0.0F;
}
this.prevRotationPitch = this.rotationPitch;
this.prevRotationYaw = this.rotationYaw;
this.updateBoundingBox();
}
protected void updateBoundingBox() {
if (this.getFacingDirection() != null) {
this.posX =
(double) this.hangingPosition.getX() + 0.5 - (double) this.getFacingDirection().getXOffset() * 0.5;
this.posY =
(double) this.hangingPosition.getY() + 0.5 - (double) this.getFacingDirection().getYOffset() * 0.5;
this.posZ =
(double) this.hangingPosition.getZ() + 0.5 - (double) this.getFacingDirection().getZOffset() * 0.5;
double d1 = (double) this.getWidthPixels();
double d2 = (double) this.getHeightPixels();
double d3 = (double) this.getWidthPixels();
Axis axis = this.getFacingDirection().getAxis();
double depth = 2 - 1 / 128f;
switch (axis) {
case X:
d1 = depth;
break;
case Y:
d2 = depth;
break;
case Z:
d3 = depth;
}
d1 = d1 / 32.0D;
d2 = d2 / 32.0D;
d3 = d3 / 32.0D;
this.setBoundingBox(new AxisAlignedBB(this.posX - d1, this.posY - d2, this.posZ - d3, this.posX + d1,
this.posY + d2, this.posZ + d3));
}
}
@Override
public void tick() {
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if (this.validationTimer++ == 10 && !this.world.isRemote) {
this.validationTimer = 0;
if (isAlive() && !this.onValidSurface()) {
remove();
onBroken(null);
}
}
}
public boolean onValidSurface() {
BlockPos pos = hangingPosition;
BlockPos pos2 = hangingPosition.offset(getFacingDirection().getOpposite());
if (!world.isAreaLoaded(pos, 0) || !world.isAreaLoaded(pos2, 0))
return true;
if (world.isAirBlock(pos) && world.isAirBlock(pos2))
return false;
return world.getEntitiesInAABBexcluding(this, getBoundingBox(), e -> e instanceof SuperGlueEntity).isEmpty();
}
@Override
public boolean canBeCollidedWith() {
return true;
}
@Override
public boolean hitByEntity(Entity entity) {
return entity instanceof PlayerEntity
? attackEntityFrom(DamageSource.causePlayerDamage((PlayerEntity) entity), 0)
: false;
}
@Override
public Direction getHorizontalFacing() {
return this.getFacingDirection();
}
@Override
public boolean attackEntityFrom(DamageSource source, float amount) {
if (this.isInvulnerableTo(source))
return false;
if (isAlive() && !world.isRemote) {
remove();
markVelocityChanged();
onBroken(source.getTrueSource());
}
return true;
}
@Override
public void move(MoverType typeIn, Vec3d pos) {
if (!world.isRemote && isAlive() && pos.lengthSquared() > 0.0D) {
remove();
onBroken(null);
}
}
@Override
public void addVelocity(double x, double y, double z) {
if (!world.isRemote && isAlive() && x * x + y * y + z * z > 0.0D) {
remove();
onBroken(null);
}
}
@Override
protected float getEyeHeight(Pose poseIn, EntitySize sizeIn) {
return 0.0F;
}
@Override
public ItemStack getPickedResult(RayTraceResult target) {
return AllItems.SUPER_GLUE.asStack();
}
@Override
@OnlyIn(Dist.CLIENT)
public int getBrightnessForRender() {
BlockPos blockpos = hangingPosition;
BlockPos blockpos2 = blockpos.offset(this.getFacingDirection().getOpposite());
PlayerEntity player = Minecraft.getInstance().player;
boolean holdingGlue = AllItems.SUPER_GLUE.typeOf(player.getHeldItemMainhand())
|| AllItems.SUPER_GLUE.typeOf(player.getHeldItemOffhand());
boolean visible = world.isAirBlock(blockpos) || world.isAirBlock(blockpos2);
int minLight = holdingGlue && !visible ? 8 : 0;
int light = this.world.isBlockPresent(blockpos) ? this.world.getCombinedLight(blockpos, minLight) : 15;
int light2 = this.world.isBlockPresent(blockpos2) ? this.world.getCombinedLight(blockpos2, minLight) : 15;
return Math.max(light, light2);
}
@Override
public void applyEntityCollision(Entity entityIn) {
super.applyEntityCollision(entityIn);
}
@Override
public boolean processInitialInteract(PlayerEntity player, Hand hand) {
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
triggerPlaceBlock(player, hand);
});
return true;
}
@OnlyIn(Dist.CLIENT)
private void triggerPlaceBlock(PlayerEntity player, Hand hand) {
if (player instanceof ClientPlayerEntity && player.world instanceof ClientWorld) {
ClientPlayerEntity cPlayer = (ClientPlayerEntity) player;
Minecraft mc = Minecraft.getInstance();
RayTraceResult ray =
cPlayer.pick(mc.playerController.getBlockReachDistance(), mc.getRenderPartialTicks(), false);
if (ray instanceof BlockRayTraceResult) {
for (Hand handIn : Hand.values()) {
ItemStack itemstack = cPlayer.getHeldItem(handIn);
int countBefore = itemstack.getCount();
ActionResultType actionResultType = mc.playerController.func_217292_a(cPlayer,
(ClientWorld) cPlayer.world, handIn, (BlockRayTraceResult) ray);
if (actionResultType == ActionResultType.SUCCESS) {
cPlayer.swingArm(handIn);
if (!itemstack.isEmpty()
&& (itemstack.getCount() != countBefore || mc.playerController.isInCreativeMode()))
mc.gameRenderer.itemRenderer.resetEquippedProgress(handIn);
return;
}
}
}
}
}
@Override
public void writeAdditional(CompoundNBT compound) {
compound.putByte("Facing", (byte) this.getFacingDirection().getIndex());
BlockPos blockpos = this.getHangingPosition();
compound.putInt("TileX", blockpos.getX());
compound.putInt("TileY", blockpos.getY());
compound.putInt("TileZ", blockpos.getZ());
}
@Override
public void readAdditional(CompoundNBT compound) {
this.hangingPosition =
new BlockPos(compound.getInt("TileX"), compound.getInt("TileY"), compound.getInt("TileZ"));
this.facingDirection = Direction.byIndex(compound.getByte("Facing"));
updateFacingWithBoundingBox();
}
@Override
public ItemEntity entityDropItem(ItemStack stack, float offsetY) {
ItemEntity itementity =
new ItemEntity(this.world, this.posX + (double) ((float) this.getFacingDirection().getXOffset() * 0.15F),
this.posY + (double) offsetY,
this.posZ + (double) ((float) this.getFacingDirection().getZOffset() * 0.15F), stack);
itementity.setDefaultPickupDelay();
this.world.addEntity(itementity);
return itementity;
}
@Override
protected boolean shouldSetPosAfterLoading() {
return false;
}
@Override
public void setPosition(double x, double y, double z) {
hangingPosition = new BlockPos(x, y, z);
updateBoundingBox();
isAirBorne = true;
}
@Override
public float getRotatedYaw(Rotation transformRotation) {
if (this.getFacingDirection().getAxis() != Direction.Axis.Y) {
switch (transformRotation) {
case CLOCKWISE_180:
this.facingDirection = this.getFacingDirection().getOpposite();
break;
case COUNTERCLOCKWISE_90:
this.facingDirection = this.getFacingDirection().rotateYCCW();
break;
case CLOCKWISE_90:
this.facingDirection = this.getFacingDirection().rotateY();
default:
break;
}
}
float f = MathHelper.wrapDegrees(this.rotationYaw);
switch (transformRotation) {
case CLOCKWISE_180:
return f + 180.0F;
case COUNTERCLOCKWISE_90:
return f + 90.0F;
case CLOCKWISE_90:
return f + 270.0F;
default:
return f;
}
}
public BlockPos getHangingPosition() {
return this.hangingPosition;
}
@Override
public float getMirroredYaw(Mirror transformMirror) {
return this.getRotatedYaw(transformMirror.toRotation(this.getFacingDirection()));
}
public Direction getAttachedDirection(BlockPos pos) {
return !pos.equals(hangingPosition) ? getFacingDirection() : getFacingDirection().getOpposite();
}
@Override
public void onStruckByLightning(LightningBoltEntity lightningBolt) {}
@Override
public void recalculateSize() {}
public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
@SuppressWarnings("unchecked")
EntityType.Builder<SuperGlueEntity> entityBuilder = (EntityType.Builder<SuperGlueEntity>) builder;
return entityBuilder;
}
@Override
public IPacket<?> createSpawnPacket() {
return NetworkHooks.getEntitySpawningPacket(this);
}
@Override
public void writeSpawnData(PacketBuffer buffer) {
CompoundNBT compound = new CompoundNBT();
writeAdditional(compound);
buffer.writeCompoundTag(compound);
}
@Override
public void readSpawnData(PacketBuffer additionalData) {
readAdditional(additionalData.readCompoundTag());
}
public Direction getFacingDirection() {
return facingDirection;
}
}

View file

@ -0,0 +1,105 @@
package com.simibubi.create.modules.contraptions.components.contraptions.glue;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllPackets;
import com.simibubi.create.foundation.utility.RayTraceWorld;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceContext;
import net.minecraft.util.math.RayTraceResult.Type;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.event.world.BlockEvent.EntityPlaceEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.network.PacketDistributor;
@EventBusSubscriber
public class SuperGlueHandler {
public static Map<Direction, SuperGlueEntity> gatherGlue(IWorld world, BlockPos pos) {
List<SuperGlueEntity> entities = world.getEntitiesWithinAABB(SuperGlueEntity.class, new AxisAlignedBB(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) {
IWorld world = event.getWorld();
Entity entity = event.getEntity();
BlockPos pos = event.getPos();
if (entity == null || world == null || pos == null)
return;
if (event.isCanceled())
return;
if (world.isRemote())
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));
if (entity instanceof PlayerEntity)
glueInOffHandAppliesOnBlockPlace(event, pos, (PlayerEntity) entity);
}
public static void glueInOffHandAppliesOnBlockPlace(EntityPlaceEvent event, BlockPos pos, PlayerEntity placer) {
ItemStack itemstack = placer.getHeldItemOffhand();
if (!AllItems.SUPER_GLUE.typeOf(itemstack))
return;
double distance = placer.getAttribute(PlayerEntity.REACH_DISTANCE).getValue();
Vec3d start = placer.getEyePosition(1);
Vec3d look = placer.getLook(1);
Vec3d end = start.add(look.x * distance, look.y * distance, look.z * distance);
World world = placer.world;
RayTraceWorld rayTraceWorld =
new RayTraceWorld(world, (p, state) -> p.equals(pos) ? Blocks.AIR.getDefaultState() : state);
BlockRayTraceResult ray = rayTraceWorld.rayTraceBlocks(new RayTraceContext(start, end,
RayTraceContext.BlockMode.OUTLINE, RayTraceContext.FluidMode.NONE, placer));
Direction face = ray.getFace();
if (ray == null || face == null || ray.getType() == Type.MISS)
return;
if (!ray.getPos().offset(face).equals(pos)) {
event.setCanceled(true);
return;
}
SuperGlueEntity entity = new SuperGlueEntity(world, ray.getPos(), face.getOpposite());
CompoundNBT compoundnbt = itemstack.getTag();
if (compoundnbt != null)
EntityType.applyItemNBT(world, placer, entity, compoundnbt);
if (entity.onValidSurface()) {
if (!world.isRemote) {
entity.playPlaceSound();
world.addEntity(entity);
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> entity),
new GlueEffectPacket(ray.getPos(), face, true));
}
itemstack.damageItem(1, placer, SuperGlueItem::onBroken);
}
}
}

View file

@ -0,0 +1,104 @@
package com.simibubi.create.modules.contraptions.components.contraptions.glue;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class SuperGlueItem extends Item {
public SuperGlueItem(Properties properties) {
super(properties);
}
@Override
public boolean isDamageable() {
return true;
}
@Override
public int getMaxDamage(ItemStack stack) {
return 99;
}
@Override
public int getItemStackLimit(ItemStack stack) {
return 1;
}
@Override
public ActionResultType onItemUse(ItemUseContext context) {
BlockPos blockpos = context.getPos();
Direction direction = context.getFace();
BlockPos blockpos1 = blockpos.offset(direction);
PlayerEntity playerentity = context.getPlayer();
ItemStack itemstack = context.getItem();
if (playerentity != null && !this.canPlace(playerentity, direction, itemstack, blockpos1))
return ActionResultType.FAIL;
World world = context.getWorld();
SuperGlueEntity entity = new SuperGlueEntity(world, blockpos1, direction);
CompoundNBT compoundnbt = itemstack.getTag();
if (compoundnbt != null)
EntityType.applyItemNBT(world, playerentity, entity, compoundnbt);
if (!entity.onValidSurface())
return ActionResultType.FAIL;
if (!world.isRemote) {
entity.playPlaceSound();
world.addEntity(entity);
}
itemstack.damageItem(1, playerentity, SuperGlueItem::onBroken);
return ActionResultType.SUCCESS;
}
public static void onBroken(PlayerEntity player) {
}
protected boolean canPlace(PlayerEntity entity, Direction facing, ItemStack stack, BlockPos pos) {
return !World.isOutsideBuildHeight(pos) && entity.canPlayerEdit(pos, facing, stack);
}
@OnlyIn(Dist.CLIENT)
public static void spawnParticles(World world, BlockPos pos, Direction direction, boolean fullBlock) {
Vec3d vec = new Vec3d(direction.getDirectionVec());
Vec3d plane = VecHelper.planeByNormal(vec);
Vec3d facePos = VecHelper.getCenterOf(pos).add(vec.scale(.5f));
float distance = fullBlock ? 1f : .25f + .25f * (world.rand.nextFloat() - .5f);
plane = plane.scale(distance);
ItemStack stack = new ItemStack(Items.SLIME_BALL);
for (int i = fullBlock ? 40 : 15; i > 0; i--) {
Vec3d offset = VecHelper.rotate(plane, 360 * world.rand.nextFloat(), direction.getAxis());
Vec3d motion = offset.normalize().scale(1 / 16f);
if (fullBlock)
offset = new Vec3d(MathHelper.clamp(offset.x, -.5, .5), MathHelper.clamp(offset.y, -.5, .5),
MathHelper.clamp(offset.z, -.5, .5));
Vec3d particlePos = facePos.add(offset);
world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), particlePos.x, particlePos.y,
particlePos.z, motion.x, motion.y, motion.z);
}
}
}

View file

@ -0,0 +1,125 @@
package com.simibubi.create.modules.contraptions.components.contraptions.glue;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererManager;
import net.minecraft.client.renderer.model.PositionTextureVertex;
import net.minecraft.client.renderer.model.TexturedQuad;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class SuperGlueRenderer extends EntityRenderer<SuperGlueEntity> {
private ResourceLocation regular = new ResourceLocation(Create.ID, "textures/entity/super_glue/slime.png");
private ResourceLocation ghostly = new ResourceLocation(Create.ID, "textures/entity/super_glue/ghostly.png");
private TexturedQuad quad1;
private TexturedQuad quad2;
public SuperGlueRenderer(EntityRendererManager renderManager) {
super(renderManager);
initQuads();
}
@Override
protected ResourceLocation getEntityTexture(SuperGlueEntity entity) {
return isVisible(entity) ? regular : ghostly;
}
@Override
public void doRender(SuperGlueEntity entity, double x, double y, double z, float entityYaw, float partialTicks) {
Direction facing = entity.getFacingDirection();
PlayerEntity player = Minecraft.getInstance().player;
boolean visible = isVisible(entity);
boolean holdingGlue = AllItems.SUPER_GLUE.typeOf(player.getHeldItemMainhand())
|| AllItems.SUPER_GLUE.typeOf(player.getHeldItemOffhand());
holdingGlue = holdingGlue && AllConfigs.CLIENT.showHiddenSuperGlue.get();
if (!visible && !holdingGlue)
return;
GlStateManager.pushMatrix();
GlStateManager.translated(x, y, z);
GlStateManager.rotated(AngleHelper.horizontalAngle(facing), 0, 1, 0);
GlStateManager.rotated(AngleHelper.verticalAngle(facing), 1, 0, 0);
BufferBuilder buffer = Tessellator.getInstance().getBuffer();
bindEntityTexture(entity);
if (!visible) {
GlStateManager.color4f(1, 1, 1, 0.375f);
GlStateManager.enableBlend();
GlStateManager.disableDepthTest();
}
quad1.draw(buffer, 1);
quad2.draw(buffer, 1);
GlStateManager.disableBlend();
GlStateManager.enableDepthTest();
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.popMatrix();
}
private boolean isVisible(SuperGlueEntity entity) {
if (!entity.isAlive())
return false;
BlockPos pos = entity.hangingPosition;
BlockPos pos2 = pos.offset(entity.getFacingDirection().getOpposite());
return entity.world.isAirBlock(pos) != entity.world.isAirBlock(pos2);
}
private void initQuads() {
Vec3d diff = new Vec3d(Direction.SOUTH.getDirectionVec());
Vec3d extension = diff.normalize().scale(1 / 32f - 1 / 128f);
Vec3d plane = VecHelper.planeByNormal(diff);
Axis axis = Direction.getFacingFromVector(diff.x, diff.y, diff.z).getAxis();
Vec3d start = Vec3d.ZERO.subtract(extension);
Vec3d end = Vec3d.ZERO.add(extension);
plane = plane.scale(1 / 2f);
Vec3d a1 = plane.add(start);
Vec3d b1 = plane.add(end);
plane = VecHelper.rotate(plane, -90, axis);
Vec3d a2 = plane.add(start);
Vec3d b2 = plane.add(end);
plane = VecHelper.rotate(plane, -90, axis);
Vec3d a3 = plane.add(start);
Vec3d b3 = plane.add(end);
plane = VecHelper.rotate(plane, -90, axis);
Vec3d a4 = plane.add(start);
Vec3d b4 = plane.add(end);
PositionTextureVertex v11 = new PositionTextureVertex(a1, 1, 0);
PositionTextureVertex v12 = new PositionTextureVertex(a2, 1, 1);
PositionTextureVertex v13 = new PositionTextureVertex(a3, 0, 1);
PositionTextureVertex v14 = new PositionTextureVertex(a4, 0, 0);
PositionTextureVertex v21 = new PositionTextureVertex(b1, 1, 0);
PositionTextureVertex v22 = new PositionTextureVertex(b2, 1, 1);
PositionTextureVertex v23 = new PositionTextureVertex(b3, 0, 1);
PositionTextureVertex v24 = new PositionTextureVertex(b4, 0, 0);
quad1 = new TexturedQuad(new PositionTextureVertex[] { v14, v11, v12, v13 }, 0, 0, 16, 16, 16, 16);
quad2 = new TexturedQuad(new PositionTextureVertex[] { v21, v24, v23, v22 }, 0, 0, 16, 16, 16, 16);
}
}

View file

@ -89,8 +89,8 @@ public class MountedContraption extends Contraption {
} }
@Override @Override
public void disassemble(World world, BlockPos offset, Vec3d rotation) { public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) {
super.disassemble(world, offset, rotation, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state)); super.addBlocksToWorld(world, offset, rotation, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state));
} }
} }

View file

@ -170,8 +170,8 @@ public class PistonContraption extends Contraption {
} }
@Override @Override
public void disassemble(World world, BlockPos offset, Vec3d rotation) { public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) {
super.disassemble(world, offset, rotation, (pos, state) -> { super.addBlocksToWorld(world, offset, rotation, (pos, state) -> {
BlockPos pistonPos = anchor.offset(orientation, -1); BlockPos pistonPos = anchor.offset(orientation, -1);
BlockState pistonState = world.getBlockState(pistonPos); BlockState pistonState = world.getBlockState(pistonPos);
TileEntity te = world.getTileEntity(pistonPos); TileEntity te = world.getTileEntity(pistonPos);

View file

@ -6,6 +6,7 @@ import static com.simibubi.create.modules.contraptions.base.HorizontalKineticBlo
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -137,8 +138,8 @@ public class ConnectedInputHandler {
if (controllerPos1.equals(controllerPos2)) { if (controllerPos1.equals(controllerPos2)) {
MechanicalCrafterTileEntity controller = CrafterHelper.getCrafter(world, controllerPos1); MechanicalCrafterTileEntity controller = CrafterHelper.getCrafter(world, controllerPos1);
Set<BlockPos> positions = controller.input.data.stream().map(l -> controllerPos1.add(l)) Set<BlockPos> positions =
.collect(Collectors.toSet()); controller.input.data.stream().map(l -> controllerPos1.add(l)).collect(Collectors.toSet());
List<BlockPos> frontier = new LinkedList<>(); List<BlockPos> frontier = new LinkedList<>();
List<BlockPos> splitGroup = new ArrayList<>(); List<BlockPos> splitGroup = new ArrayList<>();
@ -198,8 +199,7 @@ public class ConnectedInputHandler {
crafter1.input.data.forEach(offset -> { crafter1.input.data.forEach(offset -> {
BlockPos connectedPos = crafter1.getPos().add(offset); BlockPos connectedPos = crafter1.getPos().add(offset);
modifyAndUpdate(world, connectedPos, input -> { modifyAndUpdate(world, connectedPos, input -> {});
});
}); });
crafter2.input.data.forEach(offset -> { crafter2.input.data.forEach(offset -> {
@ -229,7 +229,7 @@ public class ConnectedInputHandler {
public static class ConnectedInput { public static class ConnectedInput {
boolean isController; boolean isController;
List<BlockPos> data = new ArrayList<>(); List<BlockPos> data = Collections.synchronizedList(new ArrayList<>());
public ConnectedInput() { public ConnectedInput() {
isController = true; isController = true;

View file

@ -20,6 +20,7 @@ import com.simibubi.create.modules.contraptions.components.crafter.MechanicalCra
import com.simibubi.create.modules.contraptions.components.crafter.RecipeGridHandler.GroupedItems; import com.simibubi.create.modules.contraptions.components.crafter.RecipeGridHandler.GroupedItems;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import net.minecraft.block.BlockState;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
@ -357,8 +358,10 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity {
} }
public void eject() { public void eject() {
Vec3d ejectPos = VecHelper.getCenterOf(pos) BlockState blockState = getBlockState();
.add(new Vec3d(getBlockState().get(HORIZONTAL_FACING).getDirectionVec()).scale(.75f)); boolean present = AllBlocks.MECHANICAL_CRAFTER.typeOf(blockState);
Vec3d vec = present ? new Vec3d(blockState.get(HORIZONTAL_FACING).getDirectionVec()).scale(.75f) : Vec3d.ZERO;
Vec3d ejectPos = VecHelper.getCenterOf(pos).add(vec);
groupedItems.grid.forEach((pair, stack) -> dropItem(ejectPos, stack)); groupedItems.grid.forEach((pair, stack) -> dropItem(ejectPos, stack));
if (!inventory.getStackInSlot(0).isEmpty()) if (!inventory.getStackInSlot(0).isEmpty())
dropItem(ejectPos, inventory.getStackInSlot(0)); dropItem(ejectPos, inventory.getStackInSlot(0));

View file

@ -71,7 +71,7 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther {
if (!canConnect(world, firstPulley, pos)) if (!canConnect(world, firstPulley, pos))
return ActionResultType.FAIL; return ActionResultType.FAIL;
if (!firstPulley.equals(pos)) { if (firstPulley != null && !firstPulley.equals(pos)) {
createBelts(world, firstPulley, pos); createBelts(world, firstPulley, pos);
if (!context.getPlayer().isCreative()) if (!context.getPlayer().isCreative())

View file

@ -166,7 +166,6 @@ public class SchematicHologram {
drawBuffer(bufferBuilder); drawBuffer(bufferBuilder);
GlStateManager.popMatrix(); GlStateManager.popMatrix();
} }
GlStateManager.disableAlphaTest();
GlStateManager.disableBlend(); GlStateManager.disableBlend();
} }
} }

View file

@ -37,7 +37,6 @@
"item.create.sand_paper": "Sand Paper", "item.create.sand_paper": "Sand Paper",
"item.create.red_sand_paper": "Red Sand Paper", "item.create.red_sand_paper": "Red Sand Paper",
"item.create.super_glue": "Super Glue", "item.create.super_glue": "Super Glue",
"item.create.antioxidant": "Antioxidant Spray",
"item.create.brass_ingot": "Brass Ingot", "item.create.brass_ingot": "Brass Ingot",
"item.create.brass_sheet": "Brass Sheets", "item.create.brass_sheet": "Brass Sheets",
@ -259,6 +258,10 @@
"block.create.cocoa_log": "Cocoa Jungle Log", "block.create.cocoa_log": "Cocoa Jungle Log",
"entity.create.contraption": "Moving Contraption",
"entity.create.stationary_contraption": "Stationary Contraption",
"entity.create.super_glue": "Superglue",
"_comment": "-------------------------] UI & MESSAGES [------------------------------------------------", "_comment": "-------------------------] UI & MESSAGES [------------------------------------------------",
"death.attack.create.crush": "%1$s was processed by Crushing Wheels", "death.attack.create.crush": "%1$s was processed by Crushing Wheels",
@ -1137,6 +1140,13 @@
"tool.create.sand_paper.tooltip.condition1": "When Used", "tool.create.sand_paper.tooltip.condition1": "When Used",
"tool.create.sand_paper.tooltip.behaviour1": "Applies polish to items held in the _offhand_ or lying on the _floor_ when _looking_ _at_ _them_", "tool.create.sand_paper.tooltip.behaviour1": "Applies polish to items held in the _offhand_ or lying on the _floor_ when _looking_ _at_ _them_",
"item.create.super_glue.tooltip": "SUPER GLUE",
"item.create.super_glue.tooltip.summary": "Glue a block to another, and they will forever be inseparable.",
"item.create.super_glue.tooltip.condition1": "When Used",
"item.create.super_glue.tooltip.behaviour1": "Makes the _clicked_ _face_ of a block _sticky_. Blocks attached to sticky faces will be _dragged_ _along_ when moved by _mechanical_ _pistons_, _bearings_ and other controllers.",
"item.create.super_glue.tooltip.condition2": "When Held in Offhand",
"item.create.super_glue.tooltip.behaviour2": "_Automatically_ _attaches_ blocks placed from the main hand to the _side_ they were _placed_ _against._",
"item.create.refined_radiance.tooltip": "REFINED RADIANCE", "item.create.refined_radiance.tooltip": "REFINED RADIANCE",
"item.create.refined_radiance.tooltip.summary": "A Chromatic material forged from _absorbed_ _light_.", "item.create.refined_radiance.tooltip.summary": "A Chromatic material forged from _absorbed_ _light_.",

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 394 B

View file

@ -0,0 +1,22 @@
{
"type": "crafting_shaped",
"pattern": [
"AS",
"NA"
],
"key": {
"A": {
"tag": "forge:slimeballs"
},
"S": {
"tag": "forge:plates/iron"
},
"N": {
"tag": "forge:nuggets/iron"
}
},
"result": {
"item": "create:super_glue",
"count": 1
}
}