From c62d356f9b75df4b478a9e880f98e4d415a8aab7 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Mon, 20 Apr 2020 23:27:34 +0200 Subject: [PATCH] Superglue - Added superglue, an alternative to chassis blocks - Added some random safety checks - Fixed some more bad gl states left by event handlers --- .../java/com/simibubi/create/AllEntities.java | 6 +- .../java/com/simibubi/create/AllItems.java | 6 +- .../java/com/simibubi/create/AllPackets.java | 2 + .../com/simibubi/create/config/CClient.java | 2 + .../create/config/CDamageControl.java | 9 +- .../behaviour/ValueBoxRenderer.java | 2 + .../scrollvalue/ScrollValueRenderer.java | 1 + .../foundation/gui/ScreenElementRenderer.java | 6 +- .../create/foundation/utility/Iterate.java | 1 + .../foundation/utility/RayTraceWorld.java | 37 ++ .../foundation/utility/TessellatorHelper.java | 1 - .../components/contraptions/Contraption.java | 72 +++- .../contraptions/ContraptionEntity.java | 2 +- .../contraptions/StructureTransform.java | 4 +- .../contraptions/glue/GlueEffectPacket.java | 49 +++ .../contraptions/glue/SuperGlueEntity.java | 390 ++++++++++++++++++ .../contraptions/glue/SuperGlueHandler.java | 105 +++++ .../contraptions/glue/SuperGlueItem.java | 104 +++++ .../contraptions/glue/SuperGlueRenderer.java | 125 ++++++ .../mounted/MountedContraption.java | 4 +- .../piston/PistonContraption.java | 4 +- .../crafter/ConnectedInputHandler.java | 10 +- .../crafter/MechanicalCrafterTileEntity.java | 7 +- .../relays/belt/item/BeltConnectorItem.java | 2 +- .../schematics/client/SchematicHologram.java | 1 - .../resources/assets/create/lang/en_us.json | 12 +- .../textures/entity/super_glue/ghostly.png | Bin 0 -> 367 bytes .../textures/entity/super_glue/slime.png | Bin 0 -> 588 bytes .../create/textures/item/super_glue.png | Bin 393 -> 394 bytes .../recipes/crafting_shaped/super_glue.json | 22 + 30 files changed, 946 insertions(+), 40 deletions(-) create mode 100644 src/main/java/com/simibubi/create/foundation/utility/RayTraceWorld.java create mode 100644 src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/GlueEffectPacket.java create mode 100644 src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueEntity.java create mode 100644 src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueHandler.java create mode 100644 src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueItem.java create mode 100644 src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueRenderer.java create mode 100644 src/main/resources/assets/create/textures/entity/super_glue/ghostly.png create mode 100644 src/main/resources/assets/create/textures/entity/super_glue/slime.png create mode 100644 src/main/resources/data/create/recipes/crafting_shaped/super_glue.json diff --git a/src/main/java/com/simibubi/create/AllEntities.java b/src/main/java/com/simibubi/create/AllEntities.java index 7da80aa5f..aa9af81f1 100644 --- a/src/main/java/com/simibubi/create/AllEntities.java +++ b/src/main/java/com/simibubi/create/AllEntities.java @@ -5,6 +5,8 @@ import java.util.function.Function; import com.simibubi.create.foundation.utility.Lang; 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.glue.SuperGlueEntity; +import com.simibubi.create.modules.contraptions.components.contraptions.glue.SuperGlueRenderer; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityClassification; @@ -23,6 +25,8 @@ public enum AllEntities { ContraptionEntity::build), STATIONARY_CONTRAPTION(ContraptionEntity::new, EntityClassification.MISC, 30, 40, false, ContraptionEntity::build), + SUPER_GLUE(SuperGlueEntity::new, EntityClassification.MISC, 30, Integer.MAX_VALUE, false, SuperGlueEntity::build), + ; private IFactory factory; @@ -62,8 +66,8 @@ public enum AllEntities { @OnlyIn(value = Dist.CLIENT) public static void registerRenderers() { -// RenderingRegistry.registerEntityRenderingHandler(CardboardBoxEntity.class, CardboardBoxEntityRenderer::new); RenderingRegistry.registerEntityRenderingHandler(ContraptionEntity.class, ContraptionEntityRenderer::new); + RenderingRegistry.registerEntityRenderingHandler(SuperGlueEntity.class, SuperGlueRenderer::new); } } diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java index 24df8e14d..ee2527e0d 100644 --- a/src/main/java/com/simibubi/create/AllItems.java +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -16,6 +16,7 @@ import com.simibubi.create.foundation.utility.data.ITaggable; import com.simibubi.create.modules.IModule; import com.simibubi.create.modules.contraptions.GogglesItem; 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.gearbox.VerticalGearboxItem; import com.simibubi.create.modules.curiosities.ChromaticCompoundCubeItem; @@ -76,7 +77,7 @@ public enum AllItems { BRASS_INGOT(new TaggedItem().withForgeTags("ingots/brass")), FLOUR, - DOUGH, + DOUGH, OBSIDIAN_DUST, ROSE_QUARTZ, POLISHED_ROSE_QUARTZ, @@ -93,8 +94,7 @@ public enum AllItems { WHISK, BRASS_HAND, SLOT_COVER, - SUPER_GLUE, - ANTIOXIDANT, + SUPER_GLUE(SuperGlueItem::new), SAND_PAPER(SandPaperItem::new), RED_SAND_PAPER(SandPaperItem::new), WRENCH(WrenchItem::new), diff --git a/src/main/java/com/simibubi/create/AllPackets.java b/src/main/java/com/simibubi/create/AllPackets.java index a7ad8772e..45c5adb12 100644 --- a/src/main/java/com/simibubi/create/AllPackets.java +++ b/src/main/java/com/simibubi/create/AllPackets.java @@ -13,6 +13,7 @@ import com.simibubi.create.foundation.packet.SimplePacketBase; import com.simibubi.create.foundation.utility.ServerSpeedProvider; 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.glue.GlueEffectPacket; import com.simibubi.create.modules.contraptions.relays.advanced.sequencer.ConfigureSequencedGearshiftPacket; import com.simibubi.create.modules.curiosities.symmetry.SymmetryEffectPacket; import com.simibubi.create.modules.curiosities.zapper.ZapperBeamPacket; @@ -51,6 +52,7 @@ public enum AllPackets { CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new), CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new), TOOL_HARVEST(AbstractToolItem.HarvestPacket.class, AbstractToolItem.HarvestPacket::new), + GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new), ; diff --git a/src/main/java/com/simibubi/create/config/CClient.java b/src/main/java/com/simibubi/create/config/CClient.java index 718a2b33d..9d8a451aa 100644 --- a/src/main/java/com/simibubi/create/config/CClient.java +++ b/src/main/java/com/simibubi/create/config/CClient.java @@ -12,6 +12,8 @@ public class CClient extends ConfigBase { public ConfigFloat fanParticleDensity = f(.5f, 0, 1, "fanParticleDensity"); public ConfigBool rainbowDebug = 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 public String getName() { diff --git a/src/main/java/com/simibubi/create/config/CDamageControl.java b/src/main/java/com/simibubi/create/config/CDamageControl.java index e62192518..5d542d203 100644 --- a/src/main/java/com/simibubi/create/config/CDamageControl.java +++ b/src/main/java/com/simibubi/create/config/CDamageControl.java @@ -5,9 +5,9 @@ public class CDamageControl extends ConfigBase { public ConfigBool freezeCrushing = b(false, "freezeCrushing", Comments.freezeCrushing); public ConfigBool freezeExtractors = b(false, "freezeExtractors", Comments.freezeExtractors); public ConfigBool freezeInWorldProcessing = b(false, "freezeInWorldProcessing", Comments.freezeInWorldProcessing); - public ConfigBool freezeRotationPropagator = b(false, "freezeRotationPropagator", Comments.freezeRotationPropagator); - public ConfigBool freezeBearingConstructs = b(false, "freezeBearingConstructs", Comments.freezeBearingConstructs); - public ConfigBool freezePistonConstructs = b(false, "freezePistonConstructs", Comments.freezePistonConstructs); + public ConfigBool freezeRotationPropagator = + b(false, "freezeRotationPropagator", Comments.freezeRotationPropagator); + public ConfigBool freezeContraptions = b(false, "freezeContraptions", Comments.freezeContraptions); @Override 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 freezeRotationPropagator = "Pauses rotation logic altogether - Use if crash mentions RotationPropagators."; - static String freezeBearingConstructs = "In case Mechanical Bearings turned against you."; - static String freezePistonConstructs = "In case Mechanical Pistons pushed it too far."; + static String freezeContraptions = "In case Moving contraptions pushed it too far."; } } diff --git a/src/main/java/com/simibubi/create/foundation/behaviour/ValueBoxRenderer.java b/src/main/java/com/simibubi/create/foundation/behaviour/ValueBoxRenderer.java index 873fa7e94..3d1eba064 100644 --- a/src/main/java/com/simibubi/create/foundation/behaviour/ValueBoxRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/behaviour/ValueBoxRenderer.java @@ -71,6 +71,8 @@ public class ValueBoxRenderer { } box.render(highlighted); + GlStateManager.disableBlend(); + GlStateManager.disableAlphaTest(); } public static void renderText(ValueBox box, FontRenderer font, String text) { diff --git a/src/main/java/com/simibubi/create/foundation/behaviour/scrollvalue/ScrollValueRenderer.java b/src/main/java/com/simibubi/create/foundation/behaviour/scrollvalue/ScrollValueRenderer.java index 212634da5..55d926bcb 100644 --- a/src/main/java/com/simibubi/create/foundation/behaviour/scrollvalue/ScrollValueRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/behaviour/scrollvalue/ScrollValueRenderer.java @@ -60,6 +60,7 @@ public class ScrollValueRenderer { } } else render(world, pos, face, behaviour, highlight); + TessellatorHelper.cleanUpAfterDrawing(); GlStateManager.enableAlphaTest(); GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); diff --git a/src/main/java/com/simibubi/create/foundation/gui/ScreenElementRenderer.java b/src/main/java/com/simibubi/create/foundation/gui/ScreenElementRenderer.java index cd7bc5fb8..d6c11bc94 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ScreenElementRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ScreenElementRenderer.java @@ -67,10 +67,9 @@ public class ScreenElementRenderer { BlockRendererDispatcher blockRenderer = mc.getBlockRendererDispatcher(); IBakedModel modelToRender = null; BlockState blockToRender = null; - boolean stateMode = transformsAndModel == null; boolean fire = false; - if (stateMode) { + if (transformsAndModel == null) { blockToRender = transformsAndState.get(); fire = (blockToRender.getBlock() instanceof FireBlock); modelToRender = blockRenderer.getModelForState(blockToRender); @@ -81,7 +80,6 @@ public class ScreenElementRenderer { GlStateManager.scaled(50, -50, 50); mc.getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); - GlStateManager.pushMatrix(); if (fire) { blockRenderer.renderBlockBrightness(blockToRender, 1); @@ -97,7 +95,7 @@ public class ScreenElementRenderer { } GlStateManager.popMatrix(); - if (stateMode && !blockToRender.getFluidState().isEmpty()) { + if (blockToRender != null && !blockToRender.getFluidState().isEmpty()) { RenderHelper.disableStandardItemLighting(); Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferbuilder = tessellator.getBuffer(); diff --git a/src/main/java/com/simibubi/create/foundation/utility/Iterate.java b/src/main/java/com/simibubi/create/foundation/utility/Iterate.java index da562aa42..86a15ee16 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/Iterate.java +++ b/src/main/java/com/simibubi/create/foundation/utility/Iterate.java @@ -10,6 +10,7 @@ import net.minecraft.util.math.BlockPos; public class Iterate { public static final boolean[] trueAndFalse = { true, false }; + public static final int[] zeroAndOne = { 1, -1 }; public static final int[] positiveAndNegative = { 1, -1 }; public static final Direction[] directions = Direction.values(); public static final Direction[] horizontalDirections = getHorizontals(); diff --git a/src/main/java/com/simibubi/create/foundation/utility/RayTraceWorld.java b/src/main/java/com/simibubi/create/foundation/utility/RayTraceWorld.java new file mode 100644 index 000000000..858da32eb --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/RayTraceWorld.java @@ -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 stateGetter; + + public RayTraceWorld(IWorld template, BiFunction 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); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/TessellatorHelper.java b/src/main/java/com/simibubi/create/foundation/utility/TessellatorHelper.java index 724452f80..1ebc38283 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/TessellatorHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/TessellatorHelper.java @@ -69,7 +69,6 @@ public class TessellatorHelper { public static void cleanUpAfterDrawing() { GlStateManager.popAttributes(); GlStateManager.popMatrix(); - GlStateManager.disableAlphaTest(); GlStateManager.disableBlend(); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/Contraption.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/Contraption.java index a272f87c0..62aed5140 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/Contraption.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/Contraption.java @@ -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.components.contraptions.chassis.AbstractChassisBlock; 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.PistonState; 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.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.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.redstone.ContactBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; @@ -74,6 +76,7 @@ public abstract class Contraption { public List> actors; public CombinedInvWrapper inventory; public List customRenderTEs; + public Set> superglue; public AxisAlignedBB bounds; public boolean stalled; @@ -83,13 +86,16 @@ public abstract class Contraption { protected BlockPos anchor; List renderOrder; + List glueToRemove; public Contraption() { blocks = new HashMap<>(); storage = new HashMap<>(); actors = new ArrayList<>(); + superglue = new HashSet<>(); renderOrder = new ArrayList<>(); customRenderTEs = new ArrayList<>(); + glueToRemove = new ArrayList<>(); } public Set getColliders(World world, Direction movementDirection) { @@ -242,6 +248,8 @@ public abstract class Contraption { frontier.add(otherPartPos); } + Map superglue = SuperGlueHandler.gatherGlue(world, pos); + // Slime blocks drag adjacent blocks if possible boolean isSlimeBlock = state.getBlock() instanceof SlimeBlock; for (Direction offset : Direction.values()) { @@ -254,9 +262,18 @@ public abstract class Contraption { return false; 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); + + if (faceHasGlue) + addGlue(superglue.get(offset)); } add(pos, capture(world, pos)); @@ -325,6 +342,14 @@ public abstract class Contraption { 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 pair) { BlockInfo captured = pair.getKey(); BlockPos localPos = pos.subtract(anchor); @@ -402,6 +427,13 @@ public abstract class Contraption { 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(); nbt.getList("Storage", 10).forEach(c -> { CompoundNBT comp = (CompoundNBT) c; @@ -440,6 +472,14 @@ public abstract class Contraption { actorsNBT.add(compound); } + ListNBT superglueNBT = new ListNBT(); + for (Pair 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(); for (BlockPos pos : storage.keySet()) { CompoundNBT c = new CompoundNBT(); @@ -453,6 +493,7 @@ public abstract class Contraption { nbt.put("Blocks", blocksNBT); nbt.put("Actors", actorsNBT); + nbt.put("Superglue", superglueNBT); nbt.put("Storage", storageNBT); nbt.put("Anchor", NBTUtil.writeBlockPos(anchor)); nbt.putBoolean("Stalled", stalled); @@ -466,11 +507,7 @@ public abstract class Contraption { } public static boolean isFrozen() { - return AllConfigs.SERVER.control.freezePistonConstructs.get(); - } - - public void disassemble(World world, BlockPos offset, Vec3d rotation) { - disassemble(world, offset, rotation, (pos, state) -> false); + return AllConfigs.SERVER.control.freezeContraptions.get(); } public void removeBlocksFromWorld(IWorld world, BlockPos offset) { @@ -479,6 +516,8 @@ public abstract class Contraption { public void removeBlocksFromWorld(IWorld world, BlockPos offset, BiPredicate customRemoval) { storage.values().forEach(MountedStorage::empty); + glueToRemove.forEach(SuperGlueEntity::remove); + for (boolean brittles : Iterate.trueAndFalse) { for (BlockInfo block : blocks.values()) { 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 customPlacement) { stop(world); @@ -558,10 +601,21 @@ public abstract class Contraption { mountedStorage.fill(tileEntity); } } + } + } + for (Pair 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) { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/ContraptionEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/ContraptionEntity.java index bf2655afc..6e4f01a95 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/ContraptionEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/ContraptionEntity.java @@ -427,7 +427,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD if (getContraption() != null) { BlockPos offset = new BlockPos(getPositionVec().add(.5, .5, .5)); Vec3d rotation = new Vec3d(getRoll(1), getYaw(1), getPitch(1)); - getContraption().disassemble(world, offset, rotation); + getContraption().addBlocksToWorld(world, offset, rotation); preventMovedEntitiesFromGettingStuck(); } remove(); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/StructureTransform.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/StructureTransform.java index f685d9719..3277964a8 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/StructureTransform.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/StructureTransform.java @@ -162,14 +162,14 @@ public class StructureTransform { return state; } - protected Axis transformAxis(Axis axisIn) { + public Axis transformAxis(Axis axisIn) { Direction facing = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axisIn); facing = transformFacing(facing); Axis axis = facing.getAxis(); return axis; } - protected Direction transformFacing(Direction facing) { + public Direction transformFacing(Direction facing) { for (int i = 0; i < rotation.ordinal(); i++) facing = facing.rotateAround(rotationAxis); return facing; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/GlueEffectPacket.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/GlueEffectPacket.java new file mode 100644 index 000000000..02dfe0b48 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/GlueEffectPacket.java @@ -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.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); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueEntity.java new file mode 100644 index 000000000..e21d2cb27 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueEntity.java @@ -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 entityBuilder = (EntityType.Builder) 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; + } +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueHandler.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueHandler.java new file mode 100644 index 000000000..239240eae --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueHandler.java @@ -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 gatherGlue(IWorld world, BlockPos pos) { + List entities = world.getEntitiesWithinAABB(SuperGlueEntity.class, new AxisAlignedBB(pos)); + Map 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 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); + } + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueItem.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueItem.java new file mode 100644 index 000000000..d2668b9be --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueItem.java @@ -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); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueRenderer.java new file mode 100644 index 000000000..2e595f9d0 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/glue/SuperGlueRenderer.java @@ -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 { + + 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); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/mounted/MountedContraption.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/mounted/MountedContraption.java index 610577738..fd6697d7d 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/mounted/MountedContraption.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/mounted/MountedContraption.java @@ -89,8 +89,8 @@ public class MountedContraption extends Contraption { } @Override - public void disassemble(World world, BlockPos offset, Vec3d rotation) { - super.disassemble(world, offset, rotation, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state)); + public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) { + super.addBlocksToWorld(world, offset, rotation, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state)); } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/piston/PistonContraption.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/piston/PistonContraption.java index 0d115e2e7..33e754a46 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/piston/PistonContraption.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/piston/PistonContraption.java @@ -170,8 +170,8 @@ public class PistonContraption extends Contraption { } @Override - public void disassemble(World world, BlockPos offset, Vec3d rotation) { - super.disassemble(world, offset, rotation, (pos, state) -> { + public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) { + super.addBlocksToWorld(world, offset, rotation, (pos, state) -> { BlockPos pistonPos = anchor.offset(orientation, -1); BlockState pistonState = world.getBlockState(pistonPos); TileEntity te = world.getTileEntity(pistonPos); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/crafter/ConnectedInputHandler.java b/src/main/java/com/simibubi/create/modules/contraptions/components/crafter/ConnectedInputHandler.java index 7133fb0fd..672579ef3 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/crafter/ConnectedInputHandler.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/crafter/ConnectedInputHandler.java @@ -6,6 +6,7 @@ import static com.simibubi.create.modules.contraptions.base.HorizontalKineticBlo import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -137,8 +138,8 @@ public class ConnectedInputHandler { if (controllerPos1.equals(controllerPos2)) { MechanicalCrafterTileEntity controller = CrafterHelper.getCrafter(world, controllerPos1); - Set positions = controller.input.data.stream().map(l -> controllerPos1.add(l)) - .collect(Collectors.toSet()); + Set positions = + controller.input.data.stream().map(l -> controllerPos1.add(l)).collect(Collectors.toSet()); List frontier = new LinkedList<>(); List splitGroup = new ArrayList<>(); @@ -198,8 +199,7 @@ public class ConnectedInputHandler { crafter1.input.data.forEach(offset -> { BlockPos connectedPos = crafter1.getPos().add(offset); - modifyAndUpdate(world, connectedPos, input -> { - }); + modifyAndUpdate(world, connectedPos, input -> {}); }); crafter2.input.data.forEach(offset -> { @@ -229,7 +229,7 @@ public class ConnectedInputHandler { public static class ConnectedInput { boolean isController; - List data = new ArrayList<>(); + List data = Collections.synchronizedList(new ArrayList<>()); public ConnectedInput() { isController = true; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/crafter/MechanicalCrafterTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/crafter/MechanicalCrafterTileEntity.java index 0a538eb5b..f9be57d87 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/crafter/MechanicalCrafterTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/crafter/MechanicalCrafterTileEntity.java @@ -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.relays.belt.BeltTileEntity; +import net.minecraft.block.BlockState; import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; @@ -357,8 +358,10 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { } public void eject() { - Vec3d ejectPos = VecHelper.getCenterOf(pos) - .add(new Vec3d(getBlockState().get(HORIZONTAL_FACING).getDirectionVec()).scale(.75f)); + BlockState blockState = getBlockState(); + 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)); if (!inventory.getStackInSlot(0).isEmpty()) dropItem(ejectPos, inventory.getStackInSlot(0)); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/item/BeltConnectorItem.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/item/BeltConnectorItem.java index 2dbdf0aa7..5adcbd64d 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/item/BeltConnectorItem.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/item/BeltConnectorItem.java @@ -71,7 +71,7 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther { if (!canConnect(world, firstPulley, pos)) return ActionResultType.FAIL; - if (!firstPulley.equals(pos)) { + if (firstPulley != null && !firstPulley.equals(pos)) { createBelts(world, firstPulley, pos); if (!context.getPlayer().isCreative()) diff --git a/src/main/java/com/simibubi/create/modules/schematics/client/SchematicHologram.java b/src/main/java/com/simibubi/create/modules/schematics/client/SchematicHologram.java index 8f5f13f4b..d0b973cdc 100644 --- a/src/main/java/com/simibubi/create/modules/schematics/client/SchematicHologram.java +++ b/src/main/java/com/simibubi/create/modules/schematics/client/SchematicHologram.java @@ -166,7 +166,6 @@ public class SchematicHologram { drawBuffer(bufferBuilder); GlStateManager.popMatrix(); } - GlStateManager.disableAlphaTest(); GlStateManager.disableBlend(); } } diff --git a/src/main/resources/assets/create/lang/en_us.json b/src/main/resources/assets/create/lang/en_us.json index e39994cc4..3336eb56a 100644 --- a/src/main/resources/assets/create/lang/en_us.json +++ b/src/main/resources/assets/create/lang/en_us.json @@ -37,7 +37,6 @@ "item.create.sand_paper": "Sand Paper", "item.create.red_sand_paper": "Red Sand Paper", "item.create.super_glue": "Super Glue", - "item.create.antioxidant": "Antioxidant Spray", "item.create.brass_ingot": "Brass Ingot", "item.create.brass_sheet": "Brass Sheets", @@ -258,6 +257,10 @@ "block.create.creative_crate": "Schematicannon Creatifier", "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 [------------------------------------------------", @@ -1136,6 +1139,13 @@ "tool.create.sand_paper.tooltip.summary": "A rough paper that can be used to _polish_ _materials_. Can be automatically applied using the Deployer.", "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_", + + "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.summary": "A Chromatic material forged from _absorbed_ _light_.", diff --git a/src/main/resources/assets/create/textures/entity/super_glue/ghostly.png b/src/main/resources/assets/create/textures/entity/super_glue/ghostly.png new file mode 100644 index 0000000000000000000000000000000000000000..8a2efeeca5f116ac9515a6a5318f5c4095451377 GIT binary patch literal 367 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1en1B<7NV~B=h_qjQm#0Bo``lcXv zPP&8r;#_utSWP__M}a%bJ|A+i%3XLttnR_Y6sLPnQYHFlzLfsG`CsyH-Ge5+dvv%> zJ{s`cG3kBrdY9k1iPKYGW|VQ9`>b;R`$?0@nG1AI+sw(o?RLB{V3Nv|WtyU{g%fM` z9_eOKW_NT*l&E^tZ;reX9OW*evo_W2C>&qKG@%YfGR~XVeFXTC2Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0pUqRK~y+TWBmXB zKLaIz2}+XY5CPFCJj{{P-Kg!y8W+44l*$Bss+xF5iC$ngQ}JagRZR#gGrP&+}S8zFiFz3Se(^fS__+c9K{nsIdK;`6M8m-PSzEw{fLyS% z_Xs=;P`uz!YW)Ap+iy@F1K1lNKFC`jZ@}b0E(J4y0B!&%U@Q{!861q9!M1|{$X1I8 zL$J*t0Q1(N)yLtkKuJg-g)q$^|AN32w`GhVuYmYqZ(X^C-wUq6PGH4XcHaa$8RiWT z;03b(0oA{|^_k)FrrTgc;0AzFo1483!yhg-24!6xh6C_~^q4`%Rh>bKM~Xp%TZAD< zzk*TMPxU{B0U!V}gk6}G;pf}m4DW$S7Z%rkz*PGG9|Oa$_rDoH@|&vmWA_3%fWq9! azyJVoIQQM@e4aD_0000=AhJ+qE7YsAj%7ok>4E*ASyHA1`G@U8Zbb#<09t? P00000NkvXXu0mjf!DA!? delta 108 zcmV-y0F(cU1BnBWNl3#001m?e$8V@)0003VNkl