diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index f498b4ba5..5614a73f4 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -10,6 +10,7 @@ import com.simibubi.create.modules.IModule; import com.simibubi.create.modules.contraptions.CasingBlock; import com.simibubi.create.modules.contraptions.components.actors.DrillBlock; import com.simibubi.create.modules.contraptions.components.actors.HarvesterBlock; +import com.simibubi.create.modules.contraptions.components.actors.PortableStorageInterfaceBlock; import com.simibubi.create.modules.contraptions.components.clock.CuckooClockBlock; import com.simibubi.create.modules.contraptions.components.contraptions.bearing.MechanicalBearingBlock; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.LinearChassisBlock; @@ -70,8 +71,8 @@ import com.simibubi.create.modules.palettes.CTWindowBlock; import com.simibubi.create.modules.palettes.GlassPaneBlock; import com.simibubi.create.modules.palettes.HorizontalCTGlassBlock; import com.simibubi.create.modules.palettes.LayeredCTBlock; -import com.simibubi.create.modules.palettes.VerticalCTGlassBlock; import com.simibubi.create.modules.palettes.ScoriaBlock; +import com.simibubi.create.modules.palettes.VerticalCTGlassBlock; import com.simibubi.create.modules.schematics.block.CreativeCrateBlock; import com.simibubi.create.modules.schematics.block.SchematicTableBlock; import com.simibubi.create.modules.schematics.block.SchematicannonBlock; @@ -129,11 +130,6 @@ public enum AllBlocks { MECHANICAL_PRESS(new MechanicalPressBlock()), MECHANICAL_MIXER(new MechanicalMixerBlock()), BASIN(new BasinBlock()), - MECHANICAL_CRAFTER(new MechanicalCrafterBlock()), - - FLYWHEEL(new FlywheelBlock()), - FURNACE_ENGINE(new FurnaceEngineBlock()), - SPEED_GAUGE(new GaugeBlock(GaugeBlock.Type.SPEED)), STRESS_GAUGE(new GaugeBlock(GaugeBlock.Type.STRESS)), @@ -149,6 +145,7 @@ public enum AllBlocks { SAW(new SawBlock()), HARVESTER(new HarvesterBlock()), DEPLOYER(new DeployerBlock()), + PORTABLE_STORAGE_INTERFACE(new PortableStorageInterfaceBlock()), CART_ASSEMBLER(new CartAssemblerBlock()), MINECART_ANCHOR(new MinecartAnchorBlock()), ANALOG_LEVER(new AnalogLeverBlock()), @@ -157,6 +154,10 @@ public enum AllBlocks { COPPER_CASING(new CasingBlock("copper_casing")), BRASS_CASING(new CasingBlock("crafter_top")), + MECHANICAL_CRAFTER(new MechanicalCrafterBlock()), + FLYWHEEL(new FlywheelBlock()), + FURNACE_ENGINE(new FurnaceEngineBlock()), + __LOGISTICS__(), CONTACT(new ContactBlock()), REDSTONE_BRIDGE(new RedstoneLinkBlock()), diff --git a/src/main/java/com/simibubi/create/AllPackets.java b/src/main/java/com/simibubi/create/AllPackets.java index 59cb0ec91..60126b718 100644 --- a/src/main/java/com/simibubi/create/AllPackets.java +++ b/src/main/java/com/simibubi/create/AllPackets.java @@ -8,6 +8,8 @@ import com.simibubi.create.foundation.behaviour.filtering.FilteringCountUpdatePa import com.simibubi.create.foundation.command.ConfigureConfigPacket; import com.simibubi.create.foundation.packet.NbtPacket; import com.simibubi.create.foundation.packet.SimplePacketBase; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; +import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionStallPacket; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ConfigureChassisPacket; import com.simibubi.create.modules.contraptions.components.mixer.ConfigureMixerPacket; import com.simibubi.create.modules.contraptions.components.motor.ConfigureMotorPacket; @@ -45,8 +47,10 @@ public enum AllPackets { // Server to Client SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new), + SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new), BEAM_EFFECT(BlockzapperBeamPacket.class, BlockzapperBeamPacket::new), CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new), + CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new), ; diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index be4299224..a5a1bd046 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -1,8 +1,6 @@ package com.simibubi.create; import com.simibubi.create.foundation.advancement.AllCriterionTriggers; -import com.simibubi.create.foundation.advancement.SandpaperUseTrigger; -import net.minecraft.advancements.CriteriaTriggers; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/src/main/java/com/simibubi/create/config/CLogistics.java b/src/main/java/com/simibubi/create/config/CLogistics.java index 1ce2c7240..554fc05ba 100644 --- a/src/main/java/com/simibubi/create/config/CLogistics.java +++ b/src/main/java/com/simibubi/create/config/CLogistics.java @@ -5,7 +5,7 @@ public class CLogistics extends ConfigBase { public ConfigInt extractorDelay = i(20, 10, "extractorDelay", Comments.extractorDelay); public ConfigInt extractorInventoryScanDelay = i(40, 10, "extractorInventoryScanDelay", Comments.extractorInventoryScanDelay); public ConfigInt extractorAmount = i(16, 1, 64, "extractorAmount", Comments.extractorAmount); - public ConfigInt linkRange = i(128, 1, "extractorDelay", Comments.linkRange); + public ConfigInt linkRange = i(128, 1, "linkRange", Comments.linkRange); @Override public String getName() { diff --git a/src/main/java/com/simibubi/create/config/CServer.java b/src/main/java/com/simibubi/create/config/CServer.java index 5e48aa40a..582ea3fa7 100644 --- a/src/main/java/com/simibubi/create/config/CServer.java +++ b/src/main/java/com/simibubi/create/config/CServer.java @@ -8,6 +8,10 @@ public class CServer extends ConfigBase { public ConfigBool enablePalettes = b(true, "enablePalettes"); public ConfigBool enableLogistics = b(true, "enableLogistics"); + public ConfigGroup infrastructure = group(0, "infrastructure", Comments.infrastructure); + public ConfigInt tickrateSyncTimer = + i(20, 5, "tickrateSyncTimer", "[in Ticks]", Comments.tickrateSyncTimer, Comments.tickrateSyncTimer2); + public CKinetics kinetics = nested(0, CKinetics::new, Comments.kinetics); public CLogistics logistics = nested(0, CLogistics::new, Comments.logistics); public CSchematics schematics = nested(0, CSchematics::new, Comments.schematics); @@ -26,6 +30,10 @@ public class CServer extends ConfigBase { static String curiosities = "Everything that spins"; static String modules = "Configure which Modules should be accessible in recipes and creative menus."; static String control = "You can try inhibiting related game mechanics for troubleshooting repeated crashes."; + static String infrastructure = "The Backbone of Create"; + static String tickrateSyncTimer = + "The amount of time a server waits before sending out tickrate synchronization packets."; + static String tickrateSyncTimer2 = "These packets help animations to be more accurate when tps is below 20."; } } diff --git a/src/main/java/com/simibubi/create/foundation/advancement/SandpaperUseTrigger.java b/src/main/java/com/simibubi/create/foundation/advancement/SandpaperUseTrigger.java index 9be31fd55..91dde29d5 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/SandpaperUseTrigger.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/SandpaperUseTrigger.java @@ -2,17 +2,13 @@ package com.simibubi.create.foundation.advancement; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; -import net.minecraft.advancements.PlayerAdvancements; -import net.minecraft.advancements.criterion.CriterionInstance; import net.minecraft.advancements.criterion.ItemPredicate; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import java.util.Arrays; -import java.util.LinkedList; import java.util.List; -import java.util.Set; import java.util.function.Supplier; public class SandpaperUseTrigger extends CriterionTriggerBase { diff --git a/src/main/java/com/simibubi/create/foundation/behaviour/base/SmartTileEntity.java b/src/main/java/com/simibubi/create/foundation/behaviour/base/SmartTileEntity.java index 297a1255d..fd761ff30 100644 --- a/src/main/java/com/simibubi/create/foundation/behaviour/base/SmartTileEntity.java +++ b/src/main/java/com/simibubi/create/foundation/behaviour/base/SmartTileEntity.java @@ -58,6 +58,7 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka public void initialize() { behaviours.values().forEach(TileEntityBehaviour::initialize); + lazyTick(); } public void updateClient(CompoundNBT compound) { diff --git a/src/main/java/com/simibubi/create/foundation/behaviour/inventory/ExtractingBehaviour.java b/src/main/java/com/simibubi/create/foundation/behaviour/inventory/ExtractingBehaviour.java index 89a52e9bc..0b8dce370 100644 --- a/src/main/java/com/simibubi/create/foundation/behaviour/inventory/ExtractingBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/behaviour/inventory/ExtractingBehaviour.java @@ -33,7 +33,7 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour { super(te, attachments); customAmountFilter = stack -> 64; customFilter = stack -> true; - callback = onExtract; + setCallback(onExtract); } public ExtractingBehaviour withAmountThreshold(Function filter) { @@ -47,11 +47,15 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour { } public boolean extract() { + return extract(getAmountToExtract()); + } + + public int getAmountToExtract() { int amount = -1; FilteringBehaviour filter = get(tileEntity, FilteringBehaviour.TYPE); if (filter != null && !filter.anyAmount()) amount = filter.getAmount(); - return extract(amount); + return amount; } public boolean extract(int exactAmount) { @@ -60,11 +64,7 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour { if (AllConfigs.SERVER.control.freezeExtractors.get()) return false; - Predicate test = customFilter; - FilteringBehaviour filter = get(tileEntity, FilteringBehaviour.TYPE); - if (filter != null) - test = customFilter.and(filter::test); - + Predicate test = getFilterTest(); for (IItemHandler inv : getInventories()) { ItemStack extract = ItemStack.EMPTY; if (exactAmount != -1) @@ -81,9 +81,21 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour { return false; } + public Predicate getFilterTest() { + Predicate test = customFilter; + FilteringBehaviour filter = get(tileEntity, FilteringBehaviour.TYPE); + if (filter != null) + test = customFilter.and(filter::test); + return test; + } + @Override public IBehaviourType getType() { return TYPE; } + public void setCallback(Consumer callback) { + this.callback = callback; + } + } diff --git a/src/main/java/com/simibubi/create/foundation/behaviour/inventory/SingleTargetAutoExtractingBehaviour.java b/src/main/java/com/simibubi/create/foundation/behaviour/inventory/SingleTargetAutoExtractingBehaviour.java index 37b6f65e8..86190ca08 100644 --- a/src/main/java/com/simibubi/create/foundation/behaviour/inventory/SingleTargetAutoExtractingBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/behaviour/inventory/SingleTargetAutoExtractingBehaviour.java @@ -13,8 +13,9 @@ import net.minecraft.util.math.BlockPos; public class SingleTargetAutoExtractingBehaviour extends AutoExtractingBehaviour { - public static IBehaviourType TYPE = new IBehaviourType() { - }; + public static IBehaviourType TYPE = + new IBehaviourType() { + }; private Supplier attachmentDirection; boolean synced; @@ -28,8 +29,8 @@ public class SingleTargetAutoExtractingBehaviour extends AutoExtractingBehaviour advantageOnNextSync = false; } - public SingleTargetAutoExtractingBehaviour dontSynchronize() { - synced = false; + public SingleTargetAutoExtractingBehaviour setSynchronized(boolean sync) { + synced = sync; return this; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/AllShapes.java b/src/main/java/com/simibubi/create/foundation/utility/AllShapes.java index 2710dd88a..8a61fb1f0 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/AllShapes.java +++ b/src/main/java/com/simibubi/create/foundation/utility/AllShapes.java @@ -33,7 +33,10 @@ public class AllShapes { makeCuboidShape(4, 4, 11, 12, 12, 17)), Direction.SOUTH), FURNACE_ENGINE = VoxelShaper.forHorizontal(VoxelShapes.or( makeCuboidShape(1, 1, 0, 15, 15, 16), - makeCuboidShape(0, 0, 9, 16, 16, 14)), Direction.SOUTH) + makeCuboidShape(0, 0, 9, 16, 16, 14)), Direction.SOUTH), + PORTABLE_STORAGE_INTERFACE = VoxelShaper.forDirectional(VoxelShapes.or( + makeCuboidShape(0, 0, 0, 16, 12, 16), + makeCuboidShape(3, 12, 3, 13, 16, 13)), Direction.UP) ; diff --git a/src/main/java/com/simibubi/create/foundation/utility/NBTHelper.java b/src/main/java/com/simibubi/create/foundation/utility/NBTHelper.java index 4cf167b0f..bbe8e0efe 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/NBTHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/NBTHelper.java @@ -6,7 +6,9 @@ import java.util.function.Function; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.FloatNBT; import net.minecraft.nbt.ListNBT; +import net.minecraft.util.math.AxisAlignedBB; public class NBTHelper { @@ -44,5 +46,24 @@ public class NBTHelper { public static List readItemList(ListNBT stacks) { return readCompoundList(stacks, ItemStack::read); } + + public static ListNBT writeAABB(AxisAlignedBB bb) { + ListNBT bbtag = new ListNBT(); + bbtag.add(new FloatNBT((float) bb.minX)); + bbtag.add(new FloatNBT((float) bb.minY)); + bbtag.add(new FloatNBT((float) bb.minZ)); + bbtag.add(new FloatNBT((float) bb.maxX)); + bbtag.add(new FloatNBT((float) bb.maxY)); + bbtag.add(new FloatNBT((float) bb.maxZ)); + return bbtag; + } + + public static AxisAlignedBB readAABB(ListNBT bbtag) { + if (bbtag == null || bbtag.isEmpty()) + return null; + return new AxisAlignedBB(bbtag.getFloat(0), bbtag.getFloat(1), bbtag.getFloat(2), bbtag.getFloat(3), + bbtag.getFloat(4), bbtag.getFloat(5)); + + } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/ServerSpeedProvider.java b/src/main/java/com/simibubi/create/foundation/utility/ServerSpeedProvider.java new file mode 100644 index 000000000..e243cea21 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/ServerSpeedProvider.java @@ -0,0 +1,83 @@ +package com.simibubi.create.foundation.utility; + +import java.util.function.Supplier; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.config.AllConfigs; +import com.simibubi.create.foundation.gui.widgets.InterpolatedChasingValue; +import com.simibubi.create.foundation.packet.SimplePacketBase; + +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.TickEvent.Phase; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.network.NetworkEvent.Context; +import net.minecraftforge.fml.network.PacketDistributor; + +@EventBusSubscriber +public class ServerSpeedProvider { + + static int clientTimer = 0; + static int serverTimer = 0; + static boolean initialized = false; + static InterpolatedChasingValue modifier = new InterpolatedChasingValue().withSpeed(.25f); + + @SubscribeEvent + public static void onServerTick(TickEvent.ServerTickEvent event) { + if (event.phase == Phase.START) + return; + serverTimer++; + if (serverTimer > getSyncInterval()) { + AllPackets.channel.send(PacketDistributor.ALL.noArg(), new Packet()); + serverTimer = 0; + } + } + + public static Integer getSyncInterval() { + return AllConfigs.SERVER.tickrateSyncTimer.get(); + } + + @SubscribeEvent + public static void onClientTick(TickEvent.ClientTickEvent event) { + if (event.phase == Phase.START) + return; + modifier.tick(); + clientTimer++; + } + + public static float get() { + return modifier.value; + } + + public static class Packet extends SimplePacketBase { + + public Packet() { + } + + public Packet(PacketBuffer buffer) { + } + + @Override + public void write(PacketBuffer buffer) { + } + + @Override + public void handle(Supplier context) { + context.get().enqueueWork(() -> { + if (!initialized) { + initialized = true; + clientTimer = 0; + return; + } + float target = ((float) getSyncInterval()) / Math.max(clientTimer, 1); + modifier.target(target); + clientTimer = 0; + + }); + context.get().setPacketHandled(true); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/BlockBreakingKineticTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/BlockBreakingKineticTileEntity.java index 69cc64afa..39df9b104 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/BlockBreakingKineticTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/BlockBreakingKineticTileEntity.java @@ -23,7 +23,7 @@ import net.minecraft.world.server.ServerWorld; public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity { - private static final AtomicInteger NEXT_BREAKER_ID = new AtomicInteger(); + public static final AtomicInteger NEXT_BREAKER_ID = new AtomicInteger(); protected int ticksUntilNextProgress; protected int destroyProgress; protected int breakerId = -NEXT_BREAKER_ID.incrementAndGet(); @@ -119,6 +119,10 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity { } public boolean canBreak(BlockState stateToBreak, float blockHardness) { + return isBreakable(stateToBreak, blockHardness); + } + + public static boolean isBreakable(BlockState stateToBreak, float blockHardness) { return !(stateToBreak.getMaterial().isLiquid() || stateToBreak.getBlock() instanceof AirBlock || blockHardness == -1); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/BlockBreakingMovementBehaviour.java b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/BlockBreakingMovementBehaviour.java new file mode 100644 index 000000000..ce6089984 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/BlockBreakingMovementBehaviour.java @@ -0,0 +1,122 @@ +package com.simibubi.create.modules.contraptions.components.actors; + +import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext; + +import net.minecraft.block.BlockState; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class BlockBreakingMovementBehaviour extends MovementBehaviour { + + @Override + public void startMoving(MovementContext context) { + context.data.putInt("BreakerId", -BlockBreakingKineticTileEntity.NEXT_BREAKER_ID.incrementAndGet()); + } + + @Override + public void visitNewPosition(MovementContext context, BlockPos pos) { + World world = context.world; + BlockState stateVisited = world.getBlockState(pos); + + if (world.isRemote) + return; + if (stateVisited.getCollisionShape(world, pos).isEmpty()) + return; + if (stateVisited.getBlockHardness(world, pos) == -1) + return; + if (!canBreak(stateVisited)) + return; + + context.data.put("BreakingPos", NBTUtil.writeBlockPos(pos)); + context.stall = true; + } + + @Override + public void stopMoving(MovementContext context) { + CompoundNBT data = context.data; + if (!data.contains("BreakingPos")) + return; + + World world = context.world; + int id = data.getInt("BreakerId"); + BlockPos breakingPos = NBTUtil.readBlockPos(data.getCompound("BreakingPos")); + + data.remove("Progress"); + data.remove("TicksUntilNextProgress"); + data.remove("BreakingPos"); + + context.stall = false; + world.sendBlockBreakProgress(id, breakingPos, -1); + } + + @Override + public void tick(MovementContext context) { + CompoundNBT data = context.data; + if (!data.contains("BreakingPos")) + return; + if (context.relativeMotion.equals(Vec3d.ZERO)) { + context.stall = false; + return; + } + + int ticksUntilNextProgress = data.getInt("TicksUntilNextProgress"); + if (ticksUntilNextProgress-- > 0) { + data.putInt("TicksUntilNextProgress", ticksUntilNextProgress); + return; + } + + World world = context.world; + BlockPos breakingPos = NBTUtil.readBlockPos(data.getCompound("BreakingPos")); + int destroyProgress = data.getInt("Progress"); + int id = data.getInt("BreakerId"); + BlockState stateToBreak = world.getBlockState(breakingPos); + float blockHardness = stateToBreak.getBlockHardness(world, breakingPos); + + if (!BlockBreakingKineticTileEntity.isBreakable(stateToBreak, blockHardness) || !canBreak(stateToBreak)) { + if (destroyProgress != 0) { + destroyProgress = 0; + data.remove("Progress"); + data.remove("TicksUntilNextProgress"); + data.remove("BreakingPos"); + context.stall = false; + world.sendBlockBreakProgress(id, breakingPos, -1); + } + return; + } + + float breakSpeed = MathHelper.clamp(Math.abs(context.getAnimationSpeed()) / 500f, 1 / 128f, 16f); + destroyProgress += MathHelper.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress); + + if (destroyProgress >= 10) { + BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack)); + onBlockBroken(context, breakingPos); + ticksUntilNextProgress = -1; + world.sendBlockBreakProgress(id, breakingPos, -1); + data.remove("Progress"); + data.remove("TicksUntilNextProgress"); + data.remove("BreakingPos"); + context.stall = false; + return; + } + + ticksUntilNextProgress = (int) (blockHardness / breakSpeed); + world.sendBlockBreakProgress(id, breakingPos, (int) destroyProgress); + data.putInt("TicksUntilNextProgress", ticksUntilNextProgress); + data.putInt("Progress", destroyProgress); + } + + protected boolean canBreak(BlockState state) { + return true; + } + + protected void onBlockBroken(MovementContext context, BlockPos pos) { + + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillBlock.java index df6397cb6..43d4e918f 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillBlock.java @@ -1,36 +1,28 @@ package com.simibubi.create.modules.contraptions.components.actors; -import java.util.List; - import com.simibubi.create.foundation.block.IWithTileEntity; import com.simibubi.create.foundation.utility.AllShapes; -import com.simibubi.create.foundation.utility.SuperByteBuffer; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.modules.contraptions.base.DirectionalKineticBlock; -import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior; +import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.material.PushReaction; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; -import net.minecraft.world.server.ServerWorld; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -public class DrillBlock extends DirectionalKineticBlock - implements IHaveMovementBehavior, IWithTileEntity { +public class DrillBlock extends DirectionalKineticBlock implements IPortableBlock, IWithTileEntity { + + public static MovementBehaviour MOVEMENT = new DrillMovementBehaviour(); public DrillBlock() { super(Properties.from(Blocks.IRON_BLOCK)); @@ -76,44 +68,10 @@ public class DrillBlock extends DirectionalKineticBlock protected boolean hasStaticPart() { return true; } - - @Override - @OnlyIn(value = Dist.CLIENT) - public SuperByteBuffer renderInContraption(MovementContext context) { - return DrillTileEntityRenderer.renderInContraption(context); - } @Override - public boolean isActive(MovementContext context) { - return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.get(FACING).getOpposite()); - } - - @Override - public Vec3d getActiveAreaOffset(MovementContext context) { - return new Vec3d(context.state.get(FACING).getDirectionVec()).scale(.65f); - } - - @Override - public void visitNewPosition(MovementContext context, BlockPos pos) { - World world = context.world; - BlockState stateVisited = world.getBlockState(pos); - - if (world.isRemote) - return; - if (stateVisited.getCollisionShape(world, pos).isEmpty()) - return; - if (stateVisited.getBlockHardness(world, pos) == -1) - return; - - world.playEvent(2001, pos, Block.getStateId(stateVisited)); - List drops = Block.getDrops(stateVisited, (ServerWorld) world, pos, null); - world.setBlockState(pos, Blocks.AIR.getDefaultState()); - - for (ItemStack stack : drops) { - ItemEntity itemEntity = new ItemEntity(world, pos.getX() + .5f, pos.getY() + .25f, pos.getZ() + .5f, stack); - itemEntity.setMotion(context.motion.add(0, 0.5f, 0).scale(world.rand.nextFloat() * .3f)); - world.addEntity(itemEntity); - } + public MovementBehaviour getMovementBehaviour() { + return MOVEMENT; } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillMovementBehaviour.java b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillMovementBehaviour.java new file mode 100644 index 000000000..5e67577b6 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillMovementBehaviour.java @@ -0,0 +1,30 @@ +package com.simibubi.create.modules.contraptions.components.actors; + +import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext; + +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour { + + @Override + public boolean isActive(MovementContext context) { + return !VecHelper.isVecPointingTowards(context.relativeMotion, + context.state.get(DrillBlock.FACING).getOpposite()); + } + + @Override + public Vec3d getActiveAreaOffset(MovementContext context) { + return new Vec3d(context.state.get(DrillBlock.FACING).getDirectionVec()).scale(.65f); + } + + @Override + @OnlyIn(value = Dist.CLIENT) + public SuperByteBuffer renderInContraption(MovementContext context) { + return DrillTileEntityRenderer.renderInContraption(context); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillTileEntityRenderer.java index 95e542f1c..d7eff349b 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillTileEntityRenderer.java @@ -9,7 +9,7 @@ import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.modules.contraptions.base.IRotate; import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext; import net.minecraft.block.BlockState; import net.minecraft.util.Direction.Axis; @@ -29,9 +29,10 @@ public class DrillTileEntityRenderer extends KineticTileEntityRenderer { BlockState state = context.state; SuperByteBuffer buffer = getRotatingModel(state); - float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, state.get(FACING).getOpposite()) - ? context.getAnimationSpeed() - : 0); + float speed = (float) (context.contraption.stalled + || !VecHelper.isVecPointingTowards(context.relativeMotion, state.get(FACING).getOpposite()) + ? context.getAnimationSpeed() + : 0); Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state); float time = AnimationTickHolder.getRenderTick() / 20; float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/HarvesterBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/HarvesterBlock.java index 765fd4d6c..0ed7177f3 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/HarvesterBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/HarvesterBlock.java @@ -1,43 +1,29 @@ package com.simibubi.create.modules.contraptions.components.actors; -import java.util.List; - import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.utility.AllShapes; -import com.simibubi.create.foundation.utility.SuperByteBuffer; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior; +import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; -import net.minecraft.block.CropsBlock; import net.minecraft.block.HorizontalBlock; -import net.minecraft.block.SugarCaneBlock; import net.minecraft.block.material.PushReaction; -import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.BlockItemUseContext; -import net.minecraft.item.ItemStack; -import net.minecraft.state.IProperty; -import net.minecraft.state.IntegerProperty; import net.minecraft.state.StateContainer.Builder; -import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorldReader; -import net.minecraft.world.World; -import net.minecraft.world.server.ServerWorld; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.IPlantable; -public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBehavior { +public class HarvesterBlock extends HorizontalBlock implements IPortableBlock { + + public static MovementBehaviour MOVEMENT = new HarvesterMovementBehaviour(); public HarvesterBlock() { super(Properties.from(Blocks.IRON_BLOCK)); @@ -70,12 +56,6 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha super.fillStateContainer(builder); } - @Override - @OnlyIn(value = Dist.CLIENT) - public SuperByteBuffer renderInContraption(MovementContext context) { - return HarvesterTileEntityRenderer.renderInContraption(context); - } - @Override public BlockRenderLayer getRenderLayer() { return BlockRenderLayer.CUTOUT; @@ -94,8 +74,8 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha if (context.getFace().getAxis().isVertical()) facing = context.getPlacementHorizontalFacing().getOpposite(); else { - BlockState blockState = context.getWorld() - .getBlockState(context.getPos().offset(context.getFace().getOpposite())); + BlockState blockState = + context.getWorld().getBlockState(context.getPos().offset(context.getFace().getOpposite())); if (AllBlocks.HARVESTER.typeOf(blockState)) facing = blockState.get(HORIZONTAL_FACING); else @@ -105,118 +85,8 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha } @Override - public boolean isActive(MovementContext context) { - return !VecHelper.isVecPointingTowards(context.relativeMotion, - context.state.get(HORIZONTAL_FACING).getOpposite()); - } - - @Override - public Vec3d getActiveAreaOffset(MovementContext context) { - return new Vec3d(context.state.get(HORIZONTAL_FACING).getDirectionVec()).scale(.5); - } - - @Override - public void visitNewPosition(MovementContext context, BlockPos pos) { - World world = context.world; - BlockState stateVisited = world.getBlockState(pos); - boolean notCropButCuttable = false; - - if (world.isRemote) - return; - - if (stateVisited.getBlock() == Blocks.SUGAR_CANE) { - notCropButCuttable = true; - pos = pos.up(); - stateVisited = world.getBlockState(pos); - } - - if (!isValidCrop(world, pos, stateVisited)) { - if (isValidOther(world, pos, stateVisited)) - notCropButCuttable = true; - else - return; - } - - List drops = Block.getDrops(stateVisited, (ServerWorld) world, pos, null); - world.playEvent(2001, pos, Block.getStateId(stateVisited)); - world.setBlockState(pos, cutCrop(world, pos, stateVisited)); - - boolean seedSubtracted = notCropButCuttable; - for (ItemStack stack : drops) { - if (!seedSubtracted && stack.isItemEqual(new ItemStack(stateVisited.getBlock()))) { - stack.shrink(1); - seedSubtracted = true; - } - ItemEntity itemEntity = new ItemEntity(world, pos.getX() + .5f, pos.getY() + .25f, pos.getZ() + .5f, stack); - itemEntity.setMotion(context.motion.add(0, 0.5f, 0).scale(world.rand.nextFloat() * .3f)); - world.addEntity(itemEntity); - } - } - - private boolean isValidCrop(World world, BlockPos pos, BlockState state) { - if (state.getBlock() instanceof CropsBlock) { - CropsBlock crop = (CropsBlock) state.getBlock(); - if (!crop.isMaxAge(state)) - return false; - return true; - } - if (state.getCollisionShape(world, pos).isEmpty()) { - for (IProperty property : state.getProperties()) { - if (!(property instanceof IntegerProperty)) - continue; - if (!property.getName().equals(BlockStateProperties.AGE_0_1.getName())) - continue; - if (((IntegerProperty) property).getAllowedValues().size() - 1 != state.get((IntegerProperty) property) - .intValue()) - continue; - return true; - } - } - - return false; - } - - private boolean isValidOther(World world, BlockPos pos, BlockState state) { - if (state.getBlock() instanceof CropsBlock) - return false; - if (state.getBlock() instanceof SugarCaneBlock) - return true; - - if (state.getCollisionShape(world, pos).isEmpty()) { - for (IProperty property : state.getProperties()) { - if (!(property instanceof IntegerProperty)) - continue; - if (!property.getName().equals(BlockStateProperties.AGE_0_1.getName())) - continue; - return false; - } - - if (state.getBlock() instanceof IPlantable) - return true; - } - - return false; - } - - private BlockState cutCrop(World world, BlockPos pos, BlockState state) { - if (state.getBlock() instanceof CropsBlock) { - CropsBlock crop = (CropsBlock) state.getBlock(); - return crop.withAge(0); - } - if (state.getBlock() == Blocks.SUGAR_CANE) { - return Blocks.AIR.getDefaultState(); - } - if (state.getCollisionShape(world, pos).isEmpty()) { - for (IProperty property : state.getProperties()) { - if (!(property instanceof IntegerProperty)) - continue; - if (!property.getName().equals(BlockStateProperties.AGE_0_1.getName())) - continue; - return state.with((IntegerProperty) property, Integer.valueOf(0)); - } - } - - return Blocks.AIR.getDefaultState(); + public MovementBehaviour getMovementBehaviour() { + return MOVEMENT; } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/HarvesterMovementBehaviour.java b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/HarvesterMovementBehaviour.java new file mode 100644 index 000000000..50cbd2395 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/HarvesterMovementBehaviour.java @@ -0,0 +1,148 @@ +package com.simibubi.create.modules.contraptions.components.actors; + +import static net.minecraft.block.HorizontalBlock.HORIZONTAL_FACING; + +import org.apache.commons.lang3.mutable.MutableBoolean; + +import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.CropsBlock; +import net.minecraft.block.SugarCaneBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.state.IProperty; +import net.minecraft.state.IntegerProperty; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.math.BlockPos; +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.common.IPlantable; + +public class HarvesterMovementBehaviour extends MovementBehaviour { + + @Override + public boolean isActive(MovementContext context) { + return !VecHelper.isVecPointingTowards(context.relativeMotion, + context.state.get(HORIZONTAL_FACING).getOpposite()); + } + + @Override + @OnlyIn(value = Dist.CLIENT) + public SuperByteBuffer renderInContraption(MovementContext context) { + return HarvesterTileEntityRenderer.renderInContraption(context); + } + + @Override + public Vec3d getActiveAreaOffset(MovementContext context) { + return new Vec3d(context.state.get(HORIZONTAL_FACING).getDirectionVec()).scale(.5); + } + + @Override + public void visitNewPosition(MovementContext context, BlockPos pos) { + World world = context.world; + BlockState stateVisited = world.getBlockState(pos); + boolean notCropButCuttable = false; + + if (world.isRemote) + return; + + if (stateVisited.getBlock() == Blocks.SUGAR_CANE) { + notCropButCuttable = true; + pos = pos.up(); + stateVisited = world.getBlockState(pos); + } + + if (!isValidCrop(world, pos, stateVisited)) { + if (isValidOther(world, pos, stateVisited)) + notCropButCuttable = true; + else + return; + } + + MutableBoolean seedSubtracted = new MutableBoolean(notCropButCuttable); + BlockState state = stateVisited; + BlockHelper.destroyBlock(world, pos, 1, stack -> { + if (!seedSubtracted.getValue() && stack.isItemEqual(new ItemStack(state.getBlock()))) { + stack.shrink(1); + seedSubtracted.setTrue(); + } + dropItem(context, stack); + }); + + world.setBlockState(pos, cutCrop(world, pos, stateVisited)); + } + + private boolean isValidCrop(World world, BlockPos pos, BlockState state) { + if (state.getBlock() instanceof CropsBlock) { + CropsBlock crop = (CropsBlock) state.getBlock(); + if (!crop.isMaxAge(state)) + return false; + return true; + } + if (state.getCollisionShape(world, pos).isEmpty()) { + for (IProperty property : state.getProperties()) { + if (!(property instanceof IntegerProperty)) + continue; + if (!property.getName().equals(BlockStateProperties.AGE_0_1.getName())) + continue; + if (((IntegerProperty) property).getAllowedValues().size() - 1 != state.get((IntegerProperty) property) + .intValue()) + continue; + return true; + } + } + + return false; + } + + private boolean isValidOther(World world, BlockPos pos, BlockState state) { + if (state.getBlock() instanceof CropsBlock) + return false; + if (state.getBlock() instanceof SugarCaneBlock) + return true; + + if (state.getCollisionShape(world, pos).isEmpty()) { + for (IProperty property : state.getProperties()) { + if (!(property instanceof IntegerProperty)) + continue; + if (!property.getName().equals(BlockStateProperties.AGE_0_1.getName())) + continue; + return false; + } + + if (state.getBlock() instanceof IPlantable) + return true; + } + + return false; + } + + private BlockState cutCrop(World world, BlockPos pos, BlockState state) { + if (state.getBlock() instanceof CropsBlock) { + CropsBlock crop = (CropsBlock) state.getBlock(); + return crop.withAge(0); + } + if (state.getBlock() == Blocks.SUGAR_CANE) { + return Blocks.AIR.getDefaultState(); + } + if (state.getCollisionShape(world, pos).isEmpty()) { + for (IProperty property : state.getProperties()) { + if (!(property instanceof IntegerProperty)) + continue; + if (!property.getName().equals(BlockStateProperties.AGE_0_1.getName())) + continue; + return state.with((IntegerProperty) property, Integer.valueOf(0)); + } + } + + return Blocks.AIR.getDefaultState(); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/HarvesterTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/HarvesterTileEntityRenderer.java index 2941fab08..3567d2197 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/HarvesterTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/HarvesterTileEntityRenderer.java @@ -7,7 +7,7 @@ import com.simibubi.create.foundation.block.SafeTileEntityRendererFast; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.SuperByteBuffer; import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.BufferBuilder; @@ -19,16 +19,18 @@ import net.minecraft.world.World; public class HarvesterTileEntityRenderer extends SafeTileEntityRendererFast { @Override - public void renderFast(HarvesterTileEntity te, double x, double y, double z, float partialTicks, - int destroyStage, BufferBuilder buffer) { + public void renderFast(HarvesterTileEntity te, double x, double y, double z, float partialTicks, int destroyStage, + BufferBuilder buffer) { SuperByteBuffer superBuffer = renderHead(getWorld(), te.getPos(), te.getBlockState(), 0); superBuffer.translate(x, y, z).renderInto(buffer); } public static SuperByteBuffer renderInContraption(MovementContext context) { BlockState state = context.state; - float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, state.get(HORIZONTAL_FACING).getOpposite()) - ? context.getAnimationSpeed() * state.get(HORIZONTAL_FACING).getAxisDirection().getOffset() + Direction facing = state.get(HORIZONTAL_FACING); + int offset = facing.getAxisDirection().getOffset() * (facing.getAxis() == Axis.X ? 1 : -1); + float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite()) + ? context.getAnimationSpeed() * offset : 0); float time = AnimationTickHolder.getRenderTick() / 20; float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/PortableStorageInterfaceBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/PortableStorageInterfaceBlock.java new file mode 100644 index 000000000..18288a061 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/PortableStorageInterfaceBlock.java @@ -0,0 +1,39 @@ +package com.simibubi.create.modules.contraptions.components.actors; + +import com.simibubi.create.foundation.block.ProperDirectionalBlock; +import com.simibubi.create.foundation.utility.AllShapes; +import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.shapes.ISelectionContext; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.world.IBlockReader; + +public class PortableStorageInterfaceBlock extends ProperDirectionalBlock implements IPortableBlock { + + public static MovementBehaviour MOVEMENT = new StorageInterfaceMovement(); + + public PortableStorageInterfaceBlock() { + super(Properties.from(Blocks.ANDESITE)); + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + return getDefaultState().with(FACING, context.getNearestLookingDirection().getOpposite()); + } + + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + return AllShapes.PORTABLE_STORAGE_INTERFACE.get(state.get(FACING)); + } + + @Override + public MovementBehaviour getMovementBehaviour() { + return MOVEMENT; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/SawMovementBehaviour.java b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/SawMovementBehaviour.java new file mode 100644 index 000000000..cdc068cca --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/SawMovementBehaviour.java @@ -0,0 +1,60 @@ +package com.simibubi.create.modules.contraptions.components.actors; + +import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.TreeCutter; +import com.simibubi.create.foundation.utility.TreeCutter.Tree; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext; +import com.simibubi.create.modules.contraptions.components.saw.SawBlock; + +import net.minecraft.block.BlockState; +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.items.ItemHandlerHelper; + +public class SawMovementBehaviour extends BlockBreakingMovementBehaviour { + + @Override + public boolean isActive(MovementContext context) { + return SawBlock.isHorizontal(context.state); + } + + @Override + public Vec3d getActiveAreaOffset(MovementContext context) { + return new Vec3d(context.state.get(SawBlock.FACING).getDirectionVec()).scale(.65f); + } + + @Override + protected boolean canBreak(BlockState state) { + return super.canBreak(state) && state.isIn(BlockTags.LOGS); + } + + @Override + protected void onBlockBroken(MovementContext context, BlockPos pos) { + Tree tree = TreeCutter.cutTree(context.world, pos); + if (tree != null) { + for (BlockPos log : tree.logs) + BlockHelper.destroyBlock(context.world, log, 1 / 2f, stack -> dropItemFromCutTree(context, log, stack)); + for (BlockPos leaf : tree.leaves) + BlockHelper.destroyBlock(context.world, leaf, 1 / 8f, + stack -> dropItemFromCutTree(context, leaf, stack)); + } + } + + public void dropItemFromCutTree(MovementContext context, BlockPos pos, ItemStack stack) { + ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.inventory, stack, false); + if (remainder.isEmpty()) + return; + + World world = context.world; + Vec3d dropPos = VecHelper.getCenterOf(pos); + float distance = (float) dropPos.distanceTo(context.position); + ItemEntity entity = new ItemEntity(world, dropPos.x, dropPos.y, dropPos.z, remainder); + entity.setMotion(context.relativeMotion.scale(distance / 20f)); + world.addEntity(entity); + } +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/StorageInterfaceMovement.java b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/StorageInterfaceMovement.java new file mode 100644 index 000000000..168fa1fde --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/StorageInterfaceMovement.java @@ -0,0 +1,157 @@ +package com.simibubi.create.modules.contraptions.components.actors; + +import java.util.function.Predicate; + +import com.simibubi.create.config.AllConfigs; +import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour; +import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.behaviour.inventory.SingleTargetAutoExtractingBehaviour; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext; +import com.simibubi.create.modules.logistics.block.transposer.TransposerBlock; +import com.simibubi.create.modules.logistics.block.transposer.TransposerTileEntity; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemHandlerHelper; + +public class StorageInterfaceMovement extends MovementBehaviour { + + private static final String _exporting_ = "Exporting"; + private static final String _delay_ = "Delay"; + private static final String _workingPos_ = "WorkingPos"; + + @Override + public Vec3d getActiveAreaOffset(MovementContext context) { + return new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING).getDirectionVec()).scale(.65f); + } + + @Override + public void visitNewPosition(MovementContext context, BlockPos pos) { + Direction currentFacing = getCurrentFacing(context); + TransposerTileEntity transposer = getValidTransposer(context.world, pos, currentFacing.getAxis()); + if (transposer == null) + return; + context.data.put(_workingPos_, NBTUtil.writeBlockPos(pos)); + context.data.putBoolean(_exporting_, + TransposerBlock.getBlockFacing(transposer.getBlockState()) != currentFacing); + context.stall = true; + } + + @Override + public void tick(MovementContext context) { + if (!context.data.contains(_workingPos_)) + return; + if (context.world.isRemote) + return; + + BlockPos pos = NBTUtil.readBlockPos(context.data.getCompound(_workingPos_)); + TransposerTileEntity transposer = getValidTransposer(context.world, pos, getCurrentFacing(context).getAxis()); + if (transposer == null) { + reset(context); + return; + } + + int nextExtract = context.data.getInt(_delay_); + if (nextExtract > 0) { + nextExtract--; + context.data.putInt(_delay_, nextExtract); + return; + } + + boolean extract = context.data.getBoolean(_exporting_); + boolean success = false; + IItemHandlerModifiable inv = context.contraption.inventory; + SingleTargetAutoExtractingBehaviour extracting = + TileEntityBehaviour.get(transposer, SingleTargetAutoExtractingBehaviour.TYPE); + FilteringBehaviour filtering = TileEntityBehaviour.get(transposer, FilteringBehaviour.TYPE); + + if (extract) { + // Export from Contraption + Predicate test = extracting.getFilterTest(); + int exactAmount = extracting.getAmountToExtract(); + ItemStack itemExtracted = ItemStack.EMPTY; + if (exactAmount != -1) + itemExtracted = ItemHelper.extract(inv, test, exactAmount, false); + else + itemExtracted = ItemHelper.extract(inv, test, transposer::amountToExtract, false); + + if (!itemExtracted.isEmpty()) { + transposer.onExtract(itemExtracted); + success = exactAmount == -1; + } + + } else { + // Import to Contraption + if (extracting != null) { + extracting.setSynchronized(false); + extracting.withAdditionalFilter(stack -> { + if (filtering.anyAmount()) + return true; + return ItemHandlerHelper.insertItemStacked(inv, stack, true).isEmpty(); + }); + + extracting.withAmountThreshold(stack -> { + ItemStack tester = stack.copy(); + tester.setCount(64); + return 64 - ItemHandlerHelper.insertItemStacked(inv, stack, true).getCount(); + }); + + extracting.setCallback(stack -> { + ItemHandlerHelper.insertItemStacked(inv, stack, false); + }); + + success = extracting.extract() && filtering.anyAmount(); + extracting.setSynchronized(true); + transposer.applyFilteringCallbacks(); + extracting.setCallback(transposer::onExtract); + } + } + + if (!success) { + reset(context); + return; + } + + context.data.putInt(_delay_, AllConfigs.SERVER.logistics.extractorDelay.get()); + } + + @Override + public void stopMoving(MovementContext context) { + reset(context); + } + + public void reset(MovementContext context) { + context.data.remove(_workingPos_); + context.data.remove(_delay_); + context.data.remove(_exporting_); + context.stall = false; + } + + private TransposerTileEntity getValidTransposer(World world, BlockPos pos, Axis validAxis) { + TileEntity te = world.getTileEntity(pos); + if (!(te instanceof TransposerTileEntity)) + return null; + if (TransposerBlock.getBlockFacing(world.getBlockState(pos)).getAxis() != validAxis) + return null; + if (world.isBlockPowered(pos)) + return null; + return (TransposerTileEntity) te; + } + + private Direction getCurrentFacing(MovementContext context) { + Vec3d directionVec = new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING).getDirectionVec()); + directionVec = VecHelper.rotate(directionVec, context.rotation.x, context.rotation.y, context.rotation.z); + return Direction.getFacingFromVector(directionVec.x, directionVec.y, directionVec.z); + } + +} 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 87d82193d..464d22a5a 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 @@ -4,20 +4,24 @@ import static net.minecraft.state.properties.BlockStateProperties.AXIS; import static net.minecraft.state.properties.BlockStateProperties.FACING; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.BiConsumer; import java.util.function.BiPredicate; import java.util.function.Function; +import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.MutablePair; +import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; import com.simibubi.create.config.AllConfigs; -import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext; +import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.modules.contraptions.components.contraptions.bearing.BearingContraption; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity; @@ -27,14 +31,14 @@ import com.simibubi.create.modules.contraptions.components.contraptions.mounted. import com.simibubi.create.modules.contraptions.components.contraptions.piston.PistonContraption; import com.simibubi.create.modules.contraptions.components.saw.SawBlock; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.FallingBlock; -import net.minecraft.block.PistonBlock; import net.minecraft.block.ShulkerBoxBlock; import net.minecraft.block.SlimeBlock; +import net.minecraft.block.material.PushReaction; import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.FloatNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.NBTUtil; import net.minecraft.state.properties.BlockStateProperties; @@ -44,21 +48,30 @@ import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template.BlockInfo; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; public class Contraption { public Map blocks; + public Map storage; public List> actors; + public CombinedInvWrapper inventory; + public AxisAlignedBB constructCollisionBox; + public boolean stalled; + protected Set cachedColliders; protected Direction cachedColliderDirection; protected BlockPos anchor; public Contraption() { blocks = new HashMap<>(); + storage = new HashMap<>(); actors = new ArrayList<>(); } @@ -137,15 +150,22 @@ public class Contraption { return false; for (int limit = 1000; limit > 0; limit--) { - if (frontier.isEmpty()) + if (frontier.isEmpty()) { + onAssembled(world, pos); return true; + } if (!moveBlock(world, frontier.remove(0), direction, frontier, visited)) return false; - } return false; } + protected void onAssembled(World world, BlockPos pos) { + List list = + storage.values().stream().map(MountedStorage::getItemHandler).collect(Collectors.toList()); + inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); + } + protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List frontier) { return true; } @@ -417,15 +437,16 @@ public class Contraption { return true; if (blockState.getBlock() instanceof ShulkerBoxBlock) return false; - return PistonBlock.canPush(blockState, world, pos, direction, true, direction); + return blockState.getPushReaction() != PushReaction.BLOCK; } - protected BlockInfo capture(World world, BlockPos pos) { + protected Pair capture(World world, BlockPos pos) { BlockState blockstate = world.getBlockState(pos); if (AllBlocks.SAW.typeOf(blockstate)) blockstate = blockstate.with(SawBlock.RUNNING, true); CompoundNBT compoundnbt = getTileEntityNBT(world, pos); - return new BlockInfo(pos, blockstate, compoundnbt); + TileEntity tileentity = world.getTileEntity(pos); + return Pair.of(new BlockInfo(pos, blockstate, compoundnbt), tileentity); } public static CompoundNBT getTileEntityNBT(World world, BlockPos pos) { @@ -440,13 +461,20 @@ public class Contraption { return compoundnbt; } - public void add(BlockPos pos, BlockInfo block) { + public void add(BlockPos pos, Pair pair) { + BlockInfo captured = pair.getKey(); BlockPos localPos = pos.subtract(anchor); - BlockInfo blockInfo = new BlockInfo(localPos, block.state, block.nbt); - blocks.put(localPos, blockInfo); - if (block.state.getBlock() instanceof IHaveMovementBehavior) - getActors().add(MutablePair.of(blockInfo, null)); + BlockInfo blockInfo = new BlockInfo(localPos, captured.state, captured.nbt); + + if (blocks.put(localPos, blockInfo) != null) + return; constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(localPos)); + + TileEntity te = pair.getValue(); + if (te != null && MountedStorage.canUseAsStorage(te)) + storage.put(localPos, new MountedStorage(te)); + if (captured.state.getBlock() instanceof IPortableBlock) + getActors().add(MutablePair.of(blockInfo, null)); } public static Contraption fromNBT(World world, CompoundNBT nbt) { @@ -463,6 +491,7 @@ public class Contraption { } public void readNBT(World world, CompoundNBT nbt) { + blocks.clear(); nbt.getList("Blocks", 10).forEach(c -> { CompoundNBT comp = (CompoundNBT) c; BlockInfo info = new BlockInfo(NBTUtil.readBlockPos(comp.getCompound("Pos")), @@ -471,23 +500,31 @@ public class Contraption { blocks.put(info.pos, info); }); + actors.clear(); nbt.getList("Actors", 10).forEach(c -> { CompoundNBT comp = (CompoundNBT) c; BlockInfo info = blocks.get(NBTUtil.readBlockPos(comp.getCompound("Pos"))); MovementContext context = MovementContext.readNBT(world, comp); + context.contraption = this; getActors().add(MutablePair.of(info, context)); }); + storage.clear(); + nbt.getList("Storage", 10).forEach(c -> { + CompoundNBT comp = (CompoundNBT) c; + storage.put(NBTUtil.readBlockPos(comp.getCompound("Pos")), new MountedStorage(comp.getCompound("Data"))); + }); + List list = + storage.values().stream().map(MountedStorage::getItemHandler).collect(Collectors.toList()); + inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); + if (nbt.contains("BoundsFront")) - constructCollisionBox = readAABB(nbt.getList("BoundsFront", 5)); + constructCollisionBox = NBTHelper.readAABB(nbt.getList("BoundsFront", 5)); + stalled = nbt.getBoolean("Stalled"); anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor")); } - public AxisAlignedBB getCollisionBoxFront() { - return constructCollisionBox; - } - public CompoundNBT writeNBT() { CompoundNBT nbt = new CompoundNBT(); @@ -498,14 +535,14 @@ public class Contraption { if (this instanceof BearingContraption) nbt.putString("Type", "Bearing"); - ListNBT blocks = new ListNBT(); + ListNBT blocksNBT = new ListNBT(); for (BlockInfo block : this.blocks.values()) { CompoundNBT c = new CompoundNBT(); c.put("Block", NBTUtil.writeBlockState(block.state)); c.put("Pos", NBTUtil.writeBlockPos(block.pos)); if (block.nbt != null) c.put("Data", block.nbt); - blocks.add(c); + blocksNBT.add(c); } ListNBT actorsNBT = new ListNBT(); @@ -515,41 +552,37 @@ public class Contraption { actor.right.writeToNBT(compound); actorsNBT.add(compound); } + + ListNBT storageNBT = new ListNBT(); + for (BlockPos pos : storage.keySet()) { + CompoundNBT c = new CompoundNBT(); + MountedStorage mountedStorage = storage.get(pos); + if (!mountedStorage.isWorking()) + continue; + c.put("Pos", NBTUtil.writeBlockPos(pos)); + c.put("Data", mountedStorage.serialize()); + storageNBT.add(c); + } + + nbt.put("Blocks", blocksNBT); nbt.put("Actors", actorsNBT); + nbt.put("Storage", storageNBT); + nbt.put("Anchor", NBTUtil.writeBlockPos(anchor)); + nbt.putBoolean("Stalled", stalled); if (constructCollisionBox != null) { - ListNBT bb = writeAABB(constructCollisionBox); + ListNBT bb = NBTHelper.writeAABB(constructCollisionBox); nbt.put("BoundsFront", bb); } - nbt.put("Blocks", blocks); - nbt.put("Anchor", NBTUtil.writeBlockPos(anchor)); + return nbt; } - public ListNBT writeAABB(AxisAlignedBB bb) { - ListNBT bbtag = new ListNBT(); - bbtag.add(new FloatNBT((float) bb.minX)); - bbtag.add(new FloatNBT((float) bb.minY)); - bbtag.add(new FloatNBT((float) bb.minZ)); - bbtag.add(new FloatNBT((float) bb.maxX)); - bbtag.add(new FloatNBT((float) bb.maxY)); - bbtag.add(new FloatNBT((float) bb.maxZ)); - return bbtag; - } - - public AxisAlignedBB readAABB(ListNBT bbtag) { - if (bbtag == null || bbtag.isEmpty()) - return null; - return new AxisAlignedBB(bbtag.getFloat(0), bbtag.getFloat(1), bbtag.getFloat(2), bbtag.getFloat(3), - bbtag.getFloat(4), bbtag.getFloat(5)); - - } - public static boolean isFrozen() { return AllConfigs.SERVER.control.freezePistonConstructs.get(); } - public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch) { + public void disassemble(World world, BlockPos offset, float yaw, float pitch) { disassemble(world, offset, yaw, pitch, (pos, state) -> false); } @@ -566,8 +599,9 @@ public class Contraption { } } - public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch, + public void disassemble(World world, BlockPos offset, float yaw, float pitch, BiPredicate customPlacement) { + stop(world); for (BlockInfo block : blocks.values()) { BlockPos targetPos = block.pos.add(offset); BlockState state = block.state; @@ -589,7 +623,13 @@ public class Contraption { block.nbt.putInt("y", targetPos.getY()); block.nbt.putInt("z", targetPos.getZ()); tileEntity.read(block.nbt); + if (storage.containsKey(block.pos)) { + MountedStorage mountedStorage = storage.get(block.pos); + if (mountedStorage.isWorking()) + mountedStorage.fill(tileEntity); + } } + } } @@ -597,11 +637,16 @@ public class Contraption { for (MutablePair pair : actors) { BlockState blockState = pair.left.state; MovementContext context = new MovementContext(world, blockState); - ((IHaveMovementBehavior) blockState.getBlock()).startMoving(context); + context.contraption = this; + getMovement(blockState).startMoving(context); pair.setRight(context); } } + public AxisAlignedBB getCollisionBoxFront() { + return constructCollisionBox; + } + public List> getActors() { return actors; } @@ -610,4 +655,26 @@ public class Contraption { return anchor; } + public void stop(World world) { + foreachActor(world, (behaviour, ctx) -> { + behaviour.stopMoving(ctx); + ctx.position = null; + ctx.motion = Vec3d.ZERO; + ctx.relativeMotion = Vec3d.ZERO; + ctx.rotation = Vec3d.ZERO; + }); + } + + public void foreachActor(World world, BiConsumer callBack) { + for (MutablePair pair : actors) + callBack.accept(getMovement(pair.getLeft().state), pair.getRight()); + } + + protected static MovementBehaviour getMovement(BlockState state) { + Block block = state.getBlock(); + if (!(block instanceof IPortableBlock)) + return null; + return ((IPortableBlock) block).getMovementBehaviour(); + } + } \ No newline at end of file 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 8943778a0..9af7ae893 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 @@ -3,16 +3,21 @@ package com.simibubi.create.modules.contraptions.components.contraptions; import org.apache.commons.lang3.tuple.MutablePair; import com.simibubi.create.AllEntities; +import com.simibubi.create.AllPackets; import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext; +import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.item.minecart.AbstractMinecartEntity; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.NBTUtil; import net.minecraft.network.IPacket; import net.minecraft.network.PacketBuffer; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; @@ -20,8 +25,11 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.server.ServerWorld; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; import net.minecraftforge.fml.network.NetworkHooks; +import net.minecraftforge.fml.network.PacketDistributor; public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnData { @@ -29,8 +37,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD protected float initialAngle; protected BlockPos controllerPos; protected IControlContraption controllerTE; + protected Vec3d motionBeforeStall; - public float movementSpeedModifier; + private static final DataParameter STALLED = + EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN); public float prevYaw; public float prevPitch; @@ -46,6 +56,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD public ContraptionEntity(EntityType entityTypeIn, World worldIn) { super(entityTypeIn, worldIn); + motionBeforeStall = Vec3d.ZERO; } protected ContraptionEntity(World world) { @@ -59,7 +70,6 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD this.prevYaw = initialAngle; this.yaw = initialAngle; this.targetYaw = initialAngle; - movementSpeedModifier = 1; } public ContraptionEntity controlledBy(T controller) { @@ -70,8 +80,13 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD @Override public void tick() { + if (contraption == null) { + remove(); + return; + } + attachToController(); - + Entity e = getRidingEntity(); if (e != null) { Vec3d movementVector = e.getMotion(); @@ -97,7 +112,19 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD pitch = angleLerp(speed, pitch, targetPitch); } + boolean wasStalled = isStalled(); tickActors(movementVector); + if (isStalled()) { + if (!wasStalled) + motionBeforeStall = e.getMotion(); + e.setMotion(0, 0, 0); + } + + if (wasStalled && !isStalled()) { + e.setMotion(motionBeforeStall); + motionBeforeStall = Vec3d.ZERO; + } + super.tick(); return; } @@ -111,47 +138,62 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD } public void tickActors(Vec3d movementVector) { - movementSpeedModifier = 1; - float anglePitch = getPitch(1); float angleYaw = getYaw(1); float angleRoll = getRoll(1); Vec3d rotationVec = new Vec3d(angleRoll, angleYaw, anglePitch); Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO); + boolean stalledPreviously = contraption.stalled; + + if (!world.isRemote) + contraption.stalled = false; for (MutablePair pair : contraption.actors) { MovementContext context = pair.right; BlockInfo blockInfo = pair.left; - IHaveMovementBehavior actor = (IHaveMovementBehavior) blockInfo.state.getBlock(); + MovementBehaviour actor = Contraption.getMovement(blockInfo.state); Vec3d actorPosition = new Vec3d(blockInfo.pos); actorPosition = actorPosition.add(actor.getActiveAreaOffset(context)); actorPosition = VecHelper.rotate(actorPosition, angleRoll, angleYaw, anglePitch); actorPosition = actorPosition.add(rotationOffset).add(posX, posY, posZ); - Vec3d previousPosition = context.position; + boolean newPosVisited = context.position == null; BlockPos gridPosition = new BlockPos(actorPosition); - boolean newPosVisited = true; - if (previousPosition != null) { - context.motion = actorPosition.subtract(previousPosition); - Vec3d relativeMotion = context.motion; - relativeMotion = VecHelper.rotate(relativeMotion, -angleRoll, -angleYaw, -anglePitch); - context.relativeMotion = relativeMotion; - newPosVisited = !new BlockPos(previousPosition).equals(gridPosition); + if (!stalledPreviously) { + Vec3d previousPosition = context.position; + if (previousPosition != null) { + context.motion = actorPosition.subtract(previousPosition); + Vec3d relativeMotion = context.motion; + relativeMotion = VecHelper.rotate(relativeMotion, -angleRoll, -angleYaw, -anglePitch); + context.relativeMotion = relativeMotion; + newPosVisited = !new BlockPos(previousPosition).equals(gridPosition); + } } context.rotation = rotationVec; context.position = actorPosition; - + if (actor.isActive(context)) { - if (newPosVisited) + if (newPosVisited && !context.stall) actor.visitNewPosition(context, gridPosition); actor.tick(context); + contraption.stalled |= context.stall; } - if (movementSpeedModifier > context.movementSpeedModifier) - movementSpeedModifier = context.movementSpeedModifier; + } + + if (!world.isRemote) { + if (!stalledPreviously && contraption.stalled) { + if (controllerTE != null) + controllerTE.onStall(); + AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), + new ContraptionStallPacket(getEntityId(), posX, posY, posZ, yaw, pitch, roll)); + } + dataManager.set(STALLED, contraption.stalled); + } else { + contraption.stalled = isStalled(); } } @@ -171,6 +213,11 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD getShortestAngleDiff(this.pitch, pitch)); } + @Override + public void notifyDataManagerChange(DataParameter key) { + super.notifyDataManagerChange(key); + } + public void rotate(double roll, double yaw, double pitch) { // Collision and stuff @@ -242,12 +289,16 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD @Override protected void registerData() { + this.dataManager.register(STALLED, false); } @Override protected void readAdditional(CompoundNBT compound) { contraption = Contraption.fromNBT(world, compound.getCompound("Contraption")); initialAngle = compound.getFloat("InitialAngle"); + ListNBT vecNBT = compound.getList("CachedMotion", 6); + if (!vecNBT.isEmpty()) + motionBeforeStall = new Vec3d(vecNBT.getDouble(0), vecNBT.getDouble(1), vecNBT.getDouble(2)); if (compound.contains("Controller")) controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller")); prevYaw = initialAngle; @@ -256,12 +307,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD } public void attachToController() { - if (controllerPos != null && controllerTE == null) { + if (controllerPos != null && (controllerTE == null || !controllerTE.isValid())) { if (!world.isBlockPresent(controllerPos)) return; TileEntity te = world.getTileEntity(controllerPos); - if (te == null || !(te instanceof IControlContraption)) + if (te == null || !(te instanceof IControlContraption)) { remove(); + return; + } IControlContraption controllerTE = (IControlContraption) te; this.controllerTE = controllerTE; controllerTE.attach(this); @@ -272,6 +325,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD protected void writeAdditional(CompoundNBT compound) { compound.put("Contraption", getContraption().writeNBT()); compound.putFloat("InitialAngle", initialAngle); + compound.put("CachedMotion", newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z)); if (controllerPos != null) compound.put("Controller", NBTUtil.writeBlockPos(controllerPos)); } @@ -303,4 +357,24 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD return contraption; } + public boolean isStalled() { + return dataManager.get(STALLED); + } + + @OnlyIn(Dist.CLIENT) + static void handleStallPacket(ContraptionStallPacket packet) { + Entity entity = Minecraft.getInstance().world.getEntityByID(packet.entityID); + if (!(entity instanceof ContraptionEntity)) + return; + ContraptionEntity ce = (ContraptionEntity) entity; + if (ce.getRidingEntity() == null) { + ce.posX = packet.x; + ce.posY = packet.y; + ce.posZ = packet.z; + } + ce.yaw = packet.yaw; + ce.pitch = packet.pitch; + ce.roll = packet.roll; + } + } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/ContraptionRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/ContraptionRenderer.java index af06551dc..6d62fcf59 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/ContraptionRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/ContraptionRenderer.java @@ -10,7 +10,6 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.utility.PlacementSimulationWorld; import com.simibubi.create.foundation.utility.SuperByteBuffer; import com.simibubi.create.foundation.utility.SuperByteBufferCache.Compartment; -import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BlockModelRenderer; @@ -18,7 +17,8 @@ import net.minecraft.client.renderer.BlockRendererDispatcher; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockPos.MutableBlockPos; +import net.minecraft.world.LightType; import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraftforge.client.model.data.EmptyModelData; @@ -31,7 +31,7 @@ public class ContraptionRenderer { public static void render(World world, Contraption c, Consumer transform, BufferBuilder buffer) { SuperByteBuffer contraptionBuffer = CreateClient.bufferCache.get(CONTRAPTION, c, () -> renderContraption(c)); transform.accept(contraptionBuffer); - contraptionBuffer.light((lx, ly, lz) -> world.getCombinedLight(new BlockPos(lx, ly, lz), 0)).renderInto(buffer); + contraptionBuffer.light((lx, ly, lz) -> getLight(world, lx, ly, lz)).renderInto(buffer); renderActors(world, c, transform, buffer); } @@ -69,8 +69,7 @@ public class ContraptionRenderer { context.world = world; BlockInfo blockInfo = actor.getLeft(); - IHaveMovementBehavior block = (IHaveMovementBehavior) blockInfo.state.getBlock(); - SuperByteBuffer render = block.renderInContraption(context); + SuperByteBuffer render = Contraption.getMovement(blockInfo.state).renderInContraption(context); if (render == null) continue; @@ -80,8 +79,24 @@ public class ContraptionRenderer { render.translate(posX, posY, posZ); transform.accept(render); - render.light((lx, ly, lz) -> world.getCombinedLight(new BlockPos(lx, ly, lz), 0)).renderInto(buffer); + render.light((lx, ly, lz) -> getLight(world, lx, ly, lz)).renderInto(buffer); } } + public static int getLight(World world, float lx, float ly, float lz) { + MutableBlockPos pos = new MutableBlockPos(); + float sky = 0, block = 0; + float offset = 1 / 8f; + + for (float zOffset = offset; zOffset >= -offset; zOffset -= 2 * offset) + for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset) + for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) { + pos.setPos(lx + xOffset, ly + yOffset, lz + zOffset); + sky += world.getLightFor(LightType.SKY, pos) / 8f; + block += world.getLightFor(LightType.BLOCK, pos) / 8f; + } + + return ((int) sky) << 20 | ((int) block) << 4; + } + } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/ContraptionStallPacket.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/ContraptionStallPacket.java new file mode 100644 index 000000000..ac397422d --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/ContraptionStallPacket.java @@ -0,0 +1,60 @@ +package com.simibubi.create.modules.contraptions.components.contraptions; + +import java.util.function.Supplier; + +import com.simibubi.create.foundation.packet.SimplePacketBase; + +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public class ContraptionStallPacket extends SimplePacketBase { + + int entityID; + float x; + float y; + float z; + float yaw; + float pitch; + float roll; + + public ContraptionStallPacket(int entityID, double posX, double posY, double posZ, float yaw, float pitch, float roll) { + this.entityID = entityID; + this.x = (float) posX; + this.y = (float) posY; + this.z = (float) posZ; + this.yaw = yaw; + this.pitch = pitch; + this.roll = roll; + } + + public ContraptionStallPacket(PacketBuffer buffer) { + entityID = buffer.readInt(); + x = buffer.readFloat(); + y = buffer.readFloat(); + z = buffer.readFloat(); + yaw = buffer.readFloat(); + pitch = buffer.readFloat(); + roll = buffer.readFloat(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeInt(entityID); + writeAll(buffer, x, y, z, yaw, pitch, roll); + } + + @Override + public void handle(Supplier context) { + context.get().enqueueWork( + () -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ContraptionEntity.handleStallPacket(this))); + context.get().setPacketHandled(true); + } + + private void writeAll(PacketBuffer buffer, float... floats) { + for (float f : floats) + buffer.writeFloat(f); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/IControlContraption.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/IControlContraption.java index 178e5e6fd..a18e96730 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/IControlContraption.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/IControlContraption.java @@ -4,4 +4,9 @@ public interface IControlContraption { public void attach(ContraptionEntity contraption); + default void onStall() { + } + + public boolean isValid(); + } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/IHaveMovementBehavior.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/IHaveMovementBehavior.java deleted file mode 100644 index 2cede4d3b..000000000 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/IHaveMovementBehavior.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.simibubi.create.modules.contraptions.components.contraptions; - -import com.simibubi.create.foundation.utility.SuperByteBuffer; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.block.BlockState; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.NBTUtil; -import net.minecraft.util.math.BlockPos; -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.common.util.Constants.NBT; - -public interface IHaveMovementBehavior { - - public class MovementContext { - - public Vec3d position; - public Vec3d motion; - public Vec3d relativeMotion; - public Vec3d rotation; - public World world; - public BlockState state; - - public float movementSpeedModifier; - public CompoundNBT data; - - public MovementContext(World world, BlockState state) { - this.world = world; - this.state = state; - - motion = Vec3d.ZERO; - relativeMotion = Vec3d.ZERO; - rotation = Vec3d.ZERO; - position = null; - data = new CompoundNBT(); - movementSpeedModifier = 1; - } - - public float getAnimationSpeed() { - int modifier = 1000; - double length = -motion.length(); - if (Math.abs(length) < 1 / 512f) - return 0; - return (((int) (length * modifier + 100 * Math.signum(length))) / 100) * 100; - } - - public static MovementContext readNBT(World world, CompoundNBT nbt) { - BlockState state = NBTUtil.readBlockState(nbt.getCompound("State")); - MovementContext context = new MovementContext(world, state); - context.motion = VecHelper.readNBT(nbt.getList("Motion", NBT.TAG_DOUBLE)); - context.relativeMotion = VecHelper.readNBT(nbt.getList("RelativeMotion", NBT.TAG_DOUBLE)); - context.rotation = VecHelper.readNBT(nbt.getList("Rotation", NBT.TAG_DOUBLE)); - if (nbt.contains("Position")) - context.position = VecHelper.readNBT(nbt.getList("Position", NBT.TAG_DOUBLE)); - context.movementSpeedModifier = nbt.getFloat("SpeedModifier"); - context.data = nbt.getCompound("Data"); - return context; - } - - public CompoundNBT writeToNBT(CompoundNBT nbt) { - nbt.put("State", NBTUtil.writeBlockState(state)); - nbt.put("Motion", VecHelper.writeNBT(motion)); - nbt.put("RelativeMotion", VecHelper.writeNBT(relativeMotion)); - nbt.put("Rotation", VecHelper.writeNBT(rotation)); - if (position != null) - nbt.put("Position", VecHelper.writeNBT(position)); - nbt.putFloat("SpeedModifier", movementSpeedModifier); - nbt.put("Data", data); - return nbt; - } - - } - - default boolean isActive(MovementContext context) { - return true; - } - - default void tick(MovementContext context) { - } - - default void startMoving(MovementContext context) { - } - - default void visitNewPosition(MovementContext context, BlockPos pos) { - } - - default Vec3d getActiveAreaOffset(MovementContext context) { - return Vec3d.ZERO; - } - - @OnlyIn(value = Dist.CLIENT) - default SuperByteBuffer renderInContraption(MovementContext context) { - return null; - } - -} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/IPortableBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/IPortableBlock.java new file mode 100644 index 000000000..e564c3052 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/IPortableBlock.java @@ -0,0 +1,7 @@ +package com.simibubi.create.modules.contraptions.components.contraptions; + +public interface IPortableBlock { + + public MovementBehaviour getMovementBehaviour(); + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/MountedStorage.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/MountedStorage.java new file mode 100644 index 000000000..e9eb4ff87 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/MountedStorage.java @@ -0,0 +1,79 @@ +package com.simibubi.create.modules.contraptions.components.contraptions; + +import com.simibubi.create.AllTileEntities; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityType; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; + +public class MountedStorage { + + private static final ItemStackHandler dummyHandler = new ItemStackHandler(); + + ItemStackHandler handler; + boolean working; + + public MountedStorage(TileEntity te) { + handler = dummyHandler; + if (te != null) { + IItemHandler teHandler = + te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(dummyHandler); + if (teHandler != dummyHandler && teHandler instanceof IItemHandlerModifiable) { + IItemHandlerModifiable inv = (IItemHandlerModifiable) teHandler; + handler = new ItemStackHandler(teHandler.getSlots()); + for (int slot = 0; slot < handler.getSlots(); slot++) { + handler.setStackInSlot(slot, inv.getStackInSlot(slot)); + inv.setStackInSlot(slot, ItemStack.EMPTY); + } + } + } + + working = te != null && handler != dummyHandler; + } + + public MountedStorage(CompoundNBT nbt) { + handler = new ItemStackHandler(); + working = nbt != null; + if (working) + handler.deserializeNBT(nbt); + } + + public void fill(TileEntity te) { + IItemHandler teHandler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(dummyHandler); + if (teHandler != dummyHandler && teHandler instanceof IItemHandlerModifiable) { + IItemHandlerModifiable inv = (IItemHandlerModifiable) teHandler; + for (int slot = 0; slot < Math.min(inv.getSlots(), handler.getSlots()); slot++) + inv.setStackInSlot(slot, handler.getStackInSlot(slot)); + } + } + + public IItemHandlerModifiable getItemHandler() { + return handler; + } + + public CompoundNBT serialize() { + return working ? handler.serializeNBT() : null; + } + + public boolean isWorking() { + return working; + } + + public static boolean canUseAsStorage(TileEntity te) { + if (te == null) + return false; + TileEntityType type = te.getType(); + if (type == TileEntityType.CHEST || type == TileEntityType.SHULKER_BOX || type == TileEntityType.BARREL) + return true; + if (type == AllTileEntities.FLEXCRATE.type) + return true; + + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/MovementBehaviour.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/MovementBehaviour.java new file mode 100644 index 000000000..0f3c8bf0a --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/MovementBehaviour.java @@ -0,0 +1,52 @@ +package com.simibubi.create.modules.contraptions.components.contraptions; + +import com.simibubi.create.foundation.utility.SuperByteBuffer; + +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.ItemHandlerHelper; + +public abstract class MovementBehaviour { + + public boolean isActive(MovementContext context) { + return true; + } + + public void tick(MovementContext context) { + } + + public void startMoving(MovementContext context) { + } + + public void visitNewPosition(MovementContext context, BlockPos pos) { + } + + public Vec3d getActiveAreaOffset(MovementContext context) { + return Vec3d.ZERO; + } + + public void dropItem(MovementContext context, ItemStack stack) { + ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.inventory, stack, false); + if (remainder.isEmpty()) + return; + + Vec3d vec = context.position; + ItemEntity itemEntity = new ItemEntity(context.world, vec.x, vec.y, vec.z, remainder); + itemEntity.setMotion(context.motion.add(0, 0.5f, 0).scale(context.world.rand.nextFloat() * .3f)); + context.world.addEntity(itemEntity); + } + + @OnlyIn(value = Dist.CLIENT) + public SuperByteBuffer renderInContraption(MovementContext context) { + return null; + } + + public void stopMoving(MovementContext context) { + + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/MovementContext.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/MovementContext.java new file mode 100644 index 000000000..a6c8f5661 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/MovementContext.java @@ -0,0 +1,72 @@ +package com.simibubi.create.modules.contraptions.components.contraptions; + +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.block.BlockState; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.common.util.Constants.NBT; + +public class MovementContext { + + public Vec3d position; + public Vec3d motion; + public Vec3d relativeMotion; + public Vec3d rotation; + public World world; + public BlockState state; + + public boolean stall; + public CompoundNBT data; + public Contraption contraption; + + public MovementContext(World world, BlockState state) { + this.world = world; + this.state = state; + + motion = Vec3d.ZERO; + relativeMotion = Vec3d.ZERO; + rotation = Vec3d.ZERO; + position = null; + data = new CompoundNBT(); + stall = false; + } + + public float getAnimationSpeed() { + int modifier = 1000; + double length = -motion.length(); + if (world.isRemote && contraption.stalled) + return 700; + if (Math.abs(length) < 1 / 512f) + return 0; + return (((int) (length * modifier + 100 * Math.signum(length))) / 100) * 100; + } + + public static MovementContext readNBT(World world, CompoundNBT nbt) { + BlockState state = NBTUtil.readBlockState(nbt.getCompound("State")); + MovementContext context = new MovementContext(world, state); + context.motion = VecHelper.readNBT(nbt.getList("Motion", NBT.TAG_DOUBLE)); + context.relativeMotion = VecHelper.readNBT(nbt.getList("RelativeMotion", NBT.TAG_DOUBLE)); + context.rotation = VecHelper.readNBT(nbt.getList("Rotation", NBT.TAG_DOUBLE)); + if (nbt.contains("Position")) + context.position = VecHelper.readNBT(nbt.getList("Position", NBT.TAG_DOUBLE)); + context.stall = nbt.getBoolean("Stall"); + context.data = nbt.getCompound("Data"); + return context; + } + + public CompoundNBT writeToNBT(CompoundNBT nbt) { + nbt.put("State", NBTUtil.writeBlockState(state)); + nbt.put("Motion", VecHelper.writeNBT(motion)); + nbt.put("RelativeMotion", VecHelper.writeNBT(relativeMotion)); + nbt.put("Rotation", VecHelper.writeNBT(rotation)); + if (position != null) + nbt.put("Position", VecHelper.writeNBT(position)); + nbt.putBoolean("Stall", stall); + nbt.put("Data", data); + return nbt; + } + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/BearingContraption.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/BearingContraption.java index 99dd82d92..d6aa37a11 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/BearingContraption.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/BearingContraption.java @@ -1,9 +1,12 @@ package com.simibubi.create.modules.contraptions.components.contraptions.bearing; +import org.apache.commons.lang3.tuple.Pair; + import com.simibubi.create.AllBlockTags; import com.simibubi.create.modules.contraptions.components.contraptions.Contraption; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -26,10 +29,10 @@ public class BearingContraption extends Contraption { } @Override - public void add(BlockPos pos, BlockInfo block) { - if (AllBlockTags.WINDMILL_SAILS.matches(block.state)) + public void add(BlockPos pos, Pair capture) { + if (AllBlockTags.WINDMILL_SAILS.matches(capture.getKey().state)) sailBlocks++; - super.add(pos, block); + super.add(pos, capture); } @Override diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/MechanicalBearingTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/MechanicalBearingTileEntity.java index a67283b02..cf61ead0a 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/MechanicalBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/MechanicalBearingTileEntity.java @@ -1,6 +1,7 @@ package com.simibubi.create.modules.contraptions.components.contraptions.bearing; import com.simibubi.create.AllTileEntities; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.Contraption; import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity; @@ -9,6 +10,8 @@ import com.simibubi.create.modules.contraptions.components.contraptions.IControl import net.minecraft.nbt.CompoundNBT; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -30,7 +33,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp public float getAddedStressCapacity() { return isWindmill ? super.getAddedStressCapacity() : 0; } - + @Override public float getStressApplied() { return isWindmill ? 0 : super.getStressApplied(); @@ -90,6 +93,8 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp } public float getInterpolatedAngle(float partialTicks) { + if (movedContraption != null && movedContraption.isStalled()) + partialTicks = 0; return MathHelper.lerp(partialTicks, angle, angle + getAngularSpeed()); } @@ -100,7 +105,10 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp } public float getAngularSpeed() { - return getSpeed() * 3 / 10f; + float speed = getSpeed() * 3 / 10f; + if (world.isRemote) + speed *= ServerSpeedProvider.get(); + return speed; } public void assembleConstruct() { @@ -148,6 +156,8 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp if (!world.isRemote && assembleNextTick) { assembleNextTick = false; if (running) { + if (movedContraption != null) + movedContraption.getContraption().stop(world); boolean canDisassemble = Math.abs(angle) < 45 || Math.abs(angle) > 7 * 45; if (speed == 0 && (canDisassemble || movedContraption == null || movedContraption.getContraption().blocks.isEmpty())) { @@ -165,17 +175,21 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp if (!running) return; - float angularSpeed = getAngularSpeed(); - float newAngle = angle + angularSpeed; - angle = (float) (newAngle % 360); + if (!(movedContraption != null && movedContraption.isStalled())) { + float angularSpeed = getAngularSpeed(); + float newAngle = angle + angularSpeed; + angle = (float) (newAngle % 360); + } + applyRotation(); } private void applyRotation() { if (movedContraption != null) { - Direction direction = getBlockState().get(BlockStateProperties.FACING); + Axis axis = getBlockState().get(BlockStateProperties.FACING).getAxis(); + Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); Vec3d vec = new Vec3d(1, 1, 1).scale(angle).mul(new Vec3d(direction.getDirectionVec())); - movedContraption.rotateTo(vec.x, vec.y, -vec.z); + movedContraption.rotateTo(vec.x, vec.y, vec.z); } } @@ -183,6 +197,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp public void attach(ContraptionEntity contraption) { if (contraption.getContraption() instanceof BearingContraption) { this.movedContraption = contraption; + markDirty(); BlockPos anchor = pos.offset(getBlockState().get(BlockStateProperties.FACING)); movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); if (!world.isRemote) @@ -190,4 +205,15 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp } } + @Override + public void onStall() { + if (!world.isRemote) + sendData(); + } + + @Override + public boolean isValid() { + return !isRemoved(); + } + } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/MechanicalBearingTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/MechanicalBearingTileEntityRenderer.java index 2ec280958..1a804d37f 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/MechanicalBearingTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/MechanicalBearingTileEntityRenderer.java @@ -24,7 +24,7 @@ public class MechanicalBearingTileEntityRenderer extends KineticTileEntityRender superBuffer.rotateCentered(Axis.X, AngleHelper.rad(-90 - AngleHelper.verticalAngle(facing))); if (facing.getAxis().isHorizontal()) superBuffer.rotateCentered(Axis.Y, AngleHelper.rad(AngleHelper.horizontalAngle(facing.getOpposite()))); - float interpolatedAngle = bearingTe.getInterpolatedAngle(partialTicks); + float interpolatedAngle = bearingTe.getInterpolatedAngle(partialTicks - 1); kineticRotationTransform(superBuffer, bearingTe, facing.getAxis(), (float) (interpolatedAngle / 180 * Math.PI), getWorld()); superBuffer.translate(x, y, z).renderInto(buffer); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/mounted/CartAssemblerBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/mounted/CartAssemblerBlock.java index 1b15ea76e..66557fa6c 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/mounted/CartAssemblerBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/mounted/CartAssemblerBlock.java @@ -73,6 +73,8 @@ public class CartAssemblerBlock extends AbstractRailBlock { return; Contraption contraption = MountedContraption.assembleMinecart(world, pos, cart); + if (contraption == null) + return; ContraptionEntity entity = new ContraptionEntity(world, contraption, ContraptionEntity.yawFromMotion(cart.getMotion())); entity.setPosition(pos.getX(), pos.getY(), pos.getZ()); 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 64d5a58eb..27c6647ad 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 @@ -4,6 +4,8 @@ import static com.simibubi.create.modules.contraptions.components.contraptions.m import java.util.List; +import org.apache.commons.lang3.tuple.Pair; + import com.simibubi.create.AllBlocks; import com.simibubi.create.modules.contraptions.components.contraptions.Contraption; @@ -11,6 +13,7 @@ import net.minecraft.block.BlockState; import net.minecraft.entity.item.minecart.AbstractMinecartEntity; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.RailShape; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.AxisDirection; @@ -36,9 +39,9 @@ public class MountedContraption extends Contraption { return null; Axis axis = state.get(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z; - contraption.add(pos, new BlockInfo(pos, + contraption.add(pos, Pair.of(new BlockInfo(pos, AllBlocks.MINECART_ANCHOR.block.getDefaultState().with(BlockStateProperties.HORIZONTAL_AXIS, axis), - null)); + null), null)); contraption.removeBlocksFromWorld(world, BlockPos.ZERO); contraption.initActors(world); @@ -59,11 +62,13 @@ public class MountedContraption extends Contraption { } @Override - protected BlockInfo capture(World world, BlockPos pos) { - BlockInfo capture = super.capture(world, pos); + protected Pair capture(World world, BlockPos pos) { + Pair pair = super.capture(world, pos); + BlockInfo capture = pair.getKey(); if (AllBlocks.CART_ASSEMBLER.typeOf(capture.state)) - return new BlockInfo(capture.pos, CartAssemblerBlock.createAnchor(capture.state), null); - return capture; + return Pair.of(new BlockInfo(capture.pos, CartAssemblerBlock.createAnchor(capture.state), null), + pair.getValue()); + return pair; } @Override @@ -72,7 +77,7 @@ public class MountedContraption extends Contraption { } @Override - public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch) { + public void disassemble(World world, BlockPos offset, float yaw, float pitch) { super.disassemble(world, offset, yaw, pitch, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state)); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/piston/MechanicalPistonTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/piston/MechanicalPistonTileEntity.java index 2bb690a0b..34df9aadf 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/piston/MechanicalPistonTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/piston/MechanicalPistonTileEntity.java @@ -2,6 +2,7 @@ package com.simibubi.create.modules.contraptions.components.contraptions.piston; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTileEntities; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity; import com.simibubi.create.modules.contraptions.components.contraptions.IControlContraption; @@ -105,6 +106,9 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ICo public void tick() { super.tick(); + if (movedContraption != null && movedContraption.isStalled()) + return; + if (!world.isRemote && assembleNextTick) { assembleNextTick = false; if (running) { @@ -122,6 +126,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ICo return; float movementSpeed = getMovementSpeed(); + if (world.isRemote) + movementSpeed *= ServerSpeedProvider.get(); float newOffset = offset + movementSpeed; if (movedContraption == null) @@ -146,7 +152,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ICo if (movedContraption != null) { Vec3d constructOffset = getConstructOffset(0.5f); Vec3d vec = constructOffset.add(new Vec3d(movedContraption.getContraption().getAnchor())); - movedContraption.setPosition(vec.x, vec.y, vec.z); + movedContraption.move(vec.x - movedContraption.posX, vec.y - movedContraption.posY, + vec.z - movedContraption.posZ); } } @@ -234,14 +241,14 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ICo public float getMovementSpeed() { Direction pistonDirection = getBlockState().get(BlockStateProperties.FACING); - int movementModifier = pistonDirection.getAxisDirection().getOffset() - * (pistonDirection.getAxis() == Axis.Z ? -1 : 1); + int movementModifier = + pistonDirection.getAxisDirection().getOffset() * (pistonDirection.getAxis() == Axis.Z ? -1 : 1); return getSpeed() * -movementModifier / 512f; } public Vec3d getConstructOffset(float partialTicks) { - float interpolatedOffset = MathHelper.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0, - extensionLength); + float interpolatedOffset = + MathHelper.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0, extensionLength); return new Vec3d(getBlockState().get(BlockStateProperties.FACING).getDirectionVec()).scale(interpolatedOffset); } @@ -254,4 +261,15 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ICo } } + @Override + public void onStall() { + if (!world.isRemote) + sendData(); + } + + @Override + public boolean isValid() { + return !isRemoved(); + } + } 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 4c75fe697..f4fdfd43f 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 @@ -8,8 +8,11 @@ import static net.minecraft.state.properties.BlockStateProperties.FACING; import java.util.ArrayList; import java.util.List; +import org.apache.commons.lang3.tuple.Pair; + import com.simibubi.create.AllBlocks; import com.simibubi.create.config.AllConfigs; +import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.modules.contraptions.components.contraptions.Contraption; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState; @@ -132,13 +135,13 @@ public class PistonContraption extends Contraption { return true; } - public void add(BlockPos pos, BlockInfo block) { -// super.add(pos, block); - super.add(pos.offset(orientation, -initialExtensionProgress), block); + @Override + public void add(BlockPos pos, Pair capture) { + super.add(pos.offset(orientation, -initialExtensionProgress), capture); } @Override - public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch) { + public void disassemble(World world, BlockPos offset, float yaw, float pitch) { super.disassemble(world, offset, yaw, pitch, (pos, state) -> { BlockPos pistonPos = anchor.offset(orientation, -initialExtensionProgress - 1); BlockState pistonState = world.getBlockState(pistonPos); @@ -175,7 +178,7 @@ public class PistonContraption extends Contraption { initialExtensionProgress = nbt.getInt("InitialLength"); orientation = Direction.byIndex(nbt.getInt("Orientation")); if (nbt.contains("BoundsBack")) - pistonCollisionBox = readAABB(nbt.getList("BoundsBack", 5)); + pistonCollisionBox = NBTHelper.readAABB(nbt.getList("BoundsBack", 5)); } @Override @@ -183,7 +186,7 @@ public class PistonContraption extends Contraption { CompoundNBT nbt = super.writeNBT(); if (pistonCollisionBox != null) { - ListNBT bb = writeAABB(pistonCollisionBox); + ListNBT bb = NBTHelper.writeAABB(pistonCollisionBox); nbt.put("BoundsBack", bb); } nbt.putInt("InitialLength", initialExtensionProgress); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/fan/NozzleTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/fan/NozzleTileEntity.java index 2657ce22f..318159cfa 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/fan/NozzleTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/fan/NozzleTileEntity.java @@ -57,9 +57,8 @@ public class NozzleTileEntity extends SmartTileEntity { @Override public void initialize() { - super.initialize(); fanPos = pos.offset(getBlockState().get(NozzleBlock.FACING).getOpposite()); - lazyTick(); + super.initialize(); } @Override diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/flywheel/FlywheelTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/flywheel/FlywheelTileEntity.java index f272c60e3..8ee1418b0 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/flywheel/FlywheelTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/flywheel/FlywheelTileEntity.java @@ -47,11 +47,6 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity { return generatedCapacity; } - @Override - public void initialize() { - super.initialize(); - } - @Override public AxisAlignedBB getRenderBoundingBox() { return super.getRenderBoundingBox().grow(2); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/flywheel/engine/EngineTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/flywheel/engine/EngineTileEntity.java index 6a69bae21..7f77ad255 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/flywheel/engine/EngineTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/flywheel/engine/EngineTileEntity.java @@ -39,12 +39,6 @@ public class EngineTileEntity extends SmartTileEntity { return super.getRenderBoundingBox().grow(1.5f); } - @Override - public void initialize() { - super.initialize(); - lazyTick(); - } - @Override public void lazyTick() { super.lazyTick(); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawBlock.java index c3b139e76..72b272d81 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawBlock.java @@ -3,7 +3,9 @@ package com.simibubi.create.modules.contraptions.components.saw; import com.simibubi.create.foundation.block.IWithTileEntity; import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock; -import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior; +import com.simibubi.create.modules.contraptions.components.actors.SawMovementBehaviour; +import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -29,11 +31,11 @@ import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; -public class SawBlock extends DirectionalAxisKineticBlock - implements IWithTileEntity, IHaveMovementBehavior { +public class SawBlock extends DirectionalAxisKineticBlock implements IWithTileEntity, IPortableBlock { public static final BooleanProperty RUNNING = BooleanProperty.create("running"); public static DamageSource damageSourceSaw = new DamageSource("create.saw").setDamageBypassesArmor(); + public static MovementBehaviour MOVEMENT = new SawMovementBehaviour(); public SawBlock() { super(Properties.from(Blocks.ANDESITE)); @@ -103,7 +105,7 @@ public class SawBlock extends DirectionalAxisKineticBlock return PushReaction.PUSH_ONLY; } - public boolean isHorizontal(BlockState state) { + public static boolean isHorizontal(BlockState state) { return state.get(FACING).getAxis().isHorizontal(); } @@ -133,7 +135,11 @@ public class SawBlock extends DirectionalAxisKineticBlock worldIn.removeTileEntity(pos); } + } + @Override + public MovementBehaviour getMovementBehaviour() { + return MOVEMENT; } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactBlock.java index 520213a60..48eba0ce9 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactBlock.java @@ -4,8 +4,8 @@ import java.util.Random; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.block.ProperDirectionalBlock; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior; +import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -16,15 +16,14 @@ import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorld; -import net.minecraft.world.TickPriority; import net.minecraft.world.World; -public class ContactBlock extends ProperDirectionalBlock implements IHaveMovementBehavior { +public class ContactBlock extends ProperDirectionalBlock implements IPortableBlock { public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static MovementBehaviour MOVEMENT = new ContactMovementBehaviour(); public ContactBlock() { super(Properties.from(Blocks.ANDESITE)); @@ -102,33 +101,8 @@ public class ContactBlock extends ProperDirectionalBlock implements IHaveMovemen } @Override - public Vec3d getActiveAreaOffset(MovementContext context) { - return new Vec3d(context.state.get(FACING).getDirectionVec()).scale(.65f); - } - - @Override - public void visitNewPosition(MovementContext context, BlockPos pos) { - BlockState block = context.state; - World world = context.world; - - if (world.isRemote) - return; - - BlockState visitedState = world.getBlockState(pos); - if (!AllBlocks.CONTACT.typeOf(visitedState)) - return; - - Vec3d contact = new Vec3d(block.get(FACING).getDirectionVec()); - contact = VecHelper.rotate(contact, context.rotation.x, context.rotation.y, context.rotation.z); - Direction direction = Direction.getFacingFromVector(contact.x, contact.y, contact.z); - - if (!hasValidContact(world, pos.offset(direction.getOpposite()), direction)) - return; - - int ticksToStayActive = 4; - world.setBlockState(pos, visitedState.with(POWERED, true)); - world.getPendingBlockTicks().scheduleTick(pos, this, ticksToStayActive, TickPriority.NORMAL); - return; + public MovementBehaviour getMovementBehaviour() { + return MOVEMENT; } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactMovementBehaviour.java b/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactMovementBehaviour.java new file mode 100644 index 000000000..2273f2c5d --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactMovementBehaviour.java @@ -0,0 +1,60 @@ +package com.simibubi.create.modules.contraptions.redstone; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour; +import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext; + +import net.minecraft.block.BlockState; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.TickPriority; +import net.minecraft.world.World; + +public class ContactMovementBehaviour extends MovementBehaviour { + + @Override + public Vec3d getActiveAreaOffset(MovementContext context) { + return new Vec3d(context.state.get(ContactBlock.FACING).getDirectionVec()).scale(.65f); + } + + @Override + public void visitNewPosition(MovementContext context, BlockPos pos) { + BlockState block = context.state; + World world = context.world; + + if (world.isRemote) + return; + + deactivateLastVisitedContact(context); + BlockState visitedState = world.getBlockState(pos); + if (!AllBlocks.CONTACT.typeOf(visitedState)) + return; + + Vec3d contact = new Vec3d(block.get(ContactBlock.FACING).getDirectionVec()); + contact = VecHelper.rotate(contact, context.rotation.x, context.rotation.y, context.rotation.z); + Direction direction = Direction.getFacingFromVector(contact.x, contact.y, contact.z); + + if (!ContactBlock.hasValidContact(world, pos.offset(direction.getOpposite()), direction)) + return; + world.setBlockState(pos, visitedState.with(ContactBlock.POWERED, true)); + context.data.put("lastContact", NBTUtil.writeBlockPos(pos)); + return; + } + + @Override + public void stopMoving(MovementContext context) { + deactivateLastVisitedContact(context); + } + + public void deactivateLastVisitedContact(MovementContext context) { + if (context.data.contains("lastContact")) { + BlockPos last = NBTUtil.readBlockPos(context.data.getCompound("lastContact")); + context.world.getPendingBlockTicks().scheduleTick(last, AllBlocks.CONTACT.get(), 1, TickPriority.NORMAL); + context.data.remove("lastContact"); + } + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java index ccc47d1db..57fe80531 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.function.Function; import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; @@ -62,6 +63,7 @@ public class BeltInventory { float beltSpeed = belt.getDirectionAwareBeltMovementSpeed(); Direction movementFacing = belt.getMovementFacing(); float spacing = 1; + boolean onClient = belt.getWorld().isRemote; Items: while (iterator.hasNext()) { stackInFront = current; @@ -76,9 +78,10 @@ public class BeltInventory { } float movement = beltSpeed; + if (onClient) + movement *= ServerSpeedProvider.get(); // Don't move if locked - boolean onClient = belt.getWorld().isRemote; if (onClient && current.locked) continue; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/SpeedGaugeTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/SpeedGaugeTileEntity.java index e0b63e949..6a2df8656 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/SpeedGaugeTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/SpeedGaugeTileEntity.java @@ -8,7 +8,6 @@ import com.simibubi.create.modules.contraptions.GogglesItem; import com.simibubi.create.modules.contraptions.base.IRotate.SpeedLevel; import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.MathHelper; diff --git a/src/main/java/com/simibubi/create/modules/curiosities/tools/SandPaperItem.java b/src/main/java/com/simibubi/create/modules/curiosities/tools/SandPaperItem.java index b8d58688c..e4671002e 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/tools/SandPaperItem.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/tools/SandPaperItem.java @@ -1,7 +1,6 @@ package com.simibubi.create.modules.curiosities.tools; import com.simibubi.create.foundation.advancement.AllCriterionTriggers; -import com.simibubi.create.foundation.advancement.SandpaperUseTrigger; import com.simibubi.create.foundation.block.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.IHaveCustomItemModel; import com.simibubi.create.foundation.utility.VecHelper; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/transposer/TransposerTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/transposer/TransposerTileEntity.java index 92d8a97d1..59644b9ff 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/transposer/TransposerTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/transposer/TransposerTileEntity.java @@ -37,19 +37,23 @@ public class TransposerTileEntity extends ExtractorTileEntity { inserting = new InsertingBehaviour(this, Attachments.toward(() -> AttachedLogisticalBlock.getBlockFacing(getBlockState()).getOpposite())); behaviours.add(inserting); + applyFilteringCallbacks(); + } + + public void applyFilteringCallbacks() { extracting.withAmountThreshold(this::amountToExtract).withAdditionalFilter(this::shouldExtract); } public void filterChanged(ItemStack stack) { } - protected int amountToExtract(ItemStack stack) { + public int amountToExtract(ItemStack stack) { ItemStack tester = stack.copy(); tester.setCount(64); return 64 - inserting.insert(tester, true).getCount(); } - protected boolean shouldExtract(ItemStack stack) { + public boolean shouldExtract(ItemStack stack) { if (isTargetingBelt()) { Direction facing = AttachedLogisticalBlock.getBlockFacing(getBlockState()).getOpposite(); BlockPos targetPos = pos.offset(facing); @@ -79,7 +83,7 @@ public class TransposerTileEntity extends ExtractorTileEntity { } @Override - protected void onExtract(ItemStack stack) { + public void onExtract(ItemStack stack) { if (isTargetingBelt()) { Direction facing = AttachedLogisticalBlock.getBlockFacing(getBlockState()).getOpposite(); BlockPos targetPos = pos.offset(facing); diff --git a/src/main/java/com/simibubi/create/modules/schematics/block/LaunchedBlock.java b/src/main/java/com/simibubi/create/modules/schematics/block/LaunchedBlock.java new file mode 100644 index 000000000..0f9b5300d --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/schematics/block/LaunchedBlock.java @@ -0,0 +1,36 @@ +package com.simibubi.create.modules.schematics.block; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; + +public class LaunchedBlock { + + private final SchematicannonTileEntity te; + public int totalTicks; + public int ticksRemaining; + public BlockPos target; + public BlockState state; + + public LaunchedBlock(SchematicannonTileEntity schematicannonTileEntity, BlockPos target, BlockState state) { + te = schematicannonTileEntity; + this.target = target; + this.state = state; + totalTicks = (int) (Math.max(10, MathHelper.sqrt(MathHelper.sqrt(target.distanceSq(te.getPos()))) * 4f)); + ticksRemaining = totalTicks; + } + + public LaunchedBlock(SchematicannonTileEntity schematicannonTileEntity, BlockPos target, BlockState state, + int ticksLeft, int total) { + te = schematicannonTileEntity; + this.target = target; + this.state = state; + this.totalTicks = total; + this.ticksRemaining = ticksLeft; + } + + public void update() { + if (ticksRemaining > 0) + ticksRemaining--; + } +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonBlock.java b/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonBlock.java index 6dfc81c17..0107865ef 100644 --- a/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonBlock.java +++ b/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonBlock.java @@ -11,14 +11,12 @@ import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.inventory.InventoryHelper; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.Direction; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; -import net.minecraft.world.IWorld; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; import net.minecraftforge.fml.network.NetworkHooks; @@ -39,13 +37,6 @@ public class SchematicannonBlock extends Block { return new SchematicannonTileEntity(); } - @Override - public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn, - BlockPos currentPos, BlockPos facingPos) { - ((SchematicannonTileEntity) worldIn.getTileEntity(currentPos)).findInventories(); - return stateIn; - } - @Override public boolean isSolid(BlockState state) { return false; diff --git a/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonInventory.java b/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonInventory.java new file mode 100644 index 000000000..efe749b51 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonInventory.java @@ -0,0 +1,44 @@ +package com.simibubi.create.modules.schematics.block; + +import com.simibubi.create.AllItems; + +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraftforge.items.ItemStackHandler; + +public class SchematicannonInventory extends ItemStackHandler { + /** + * + */ + private final SchematicannonTileEntity te; + + public SchematicannonInventory(SchematicannonTileEntity schematicannonTileEntity) { + super(5); + te = schematicannonTileEntity; + } + + @Override + protected void onContentsChanged(int slot) { + super.onContentsChanged(slot); + te.markDirty(); + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + switch (slot) { + case 0: // Blueprint Slot + return AllItems.BLUEPRINT.typeOf(stack); + case 1: // Blueprint output + return false; + case 2: // Book input + return stack.isItemEqual(new ItemStack(Items.BOOK)) + || stack.isItemEqual(new ItemStack(Items.WRITTEN_BOOK)); + case 3: // Material List output + return false; + case 4: // Gunpowder + return stack.isItemEqual(new ItemStack(Items.GUNPOWDER)); + default: + return super.isItemValid(slot, stack); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonRenderer.java b/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonRenderer.java index 90951a9b1..581c242b9 100644 --- a/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonRenderer.java +++ b/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonRenderer.java @@ -56,7 +56,7 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer 0) - ticksRemaining--; - } - } - public SchematicannonTileEntity() { this(AllTileEntities.SCHEMATICANNON.type); } @@ -179,9 +120,10 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka public SchematicannonTileEntity(TileEntityType tileEntityTypeIn) { super(tileEntityTypeIn); + setLazyTickRate(30); attachedInventories = new LinkedList<>(); flyingBlocks = new LinkedList<>(); - inventory = new SchematicannonInventory(); + inventory = new SchematicannonInventory(this); statusMsg = "idle"; state = State.STOPPED; replaceMode = 2; @@ -271,7 +213,7 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka // Always write to Server tile if (world == null || !world.isRemote) { - flyingBlocks.add(new LaunchedBlock(readBlockPos, readBlockState, int1, int2)); + flyingBlocks.add(new LaunchedBlock(this, readBlockPos, readBlockState, int1, int2)); continue; } @@ -284,7 +226,7 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka // Add new server side blocks if (i >= flyingBlocks.size()) { - flyingBlocks.add(new LaunchedBlock(readBlockPos, readBlockState, int1, int2)); + flyingBlocks.add(new LaunchedBlock(this, readBlockPos, readBlockState, int1, int2)); continue; } @@ -346,6 +288,8 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka @Override public void tick() { + super.tick(); + if (neighbourCheckCooldown-- <= 0) { neighbourCheckCooldown = NEIGHBOUR_CHECKING; findInventories(); @@ -757,7 +701,7 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka protected void launchBlock(BlockPos target, BlockState state) { if (state.getBlock() != Blocks.AIR) blocksPlaced++; - flyingBlocks.add(new LaunchedBlock(target, state)); + flyingBlocks.add(new LaunchedBlock(this, target, state)); world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.BLOCKS, .1f, 1.1f); } @@ -817,4 +761,14 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka sendUpdate = true; } + @Override + public void addBehaviours(List behaviours) { + } + + @Override + public void lazyTick() { + super.lazyTick(); + findInventories(); + } + } diff --git a/src/main/resources/assets/create/blockstates/portable_storage_interface.json b/src/main/resources/assets/create/blockstates/portable_storage_interface.json new file mode 100644 index 000000000..038574ca8 --- /dev/null +++ b/src/main/resources/assets/create/blockstates/portable_storage_interface.json @@ -0,0 +1,16 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "create:block/portable_storage_interface" + }, + "variants": { + "facing": { + "north": { "x": 90 }, + "south": { "x": 90, "y": 180 }, + "west": { "x": 90, "y": 270 }, + "up": { }, + "down": { "x": 180 }, + "east": { "x": 90, "y": 90 } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/lang/en_us.json b/src/main/resources/assets/create/lang/en_us.json index ac642313d..4754ecdb3 100644 --- a/src/main/resources/assets/create/lang/en_us.json +++ b/src/main/resources/assets/create/lang/en_us.json @@ -96,6 +96,7 @@ "block.create.belt": "Mechanical Belt", "block.create.crushing_wheel": "Crushing Wheel", "block.create.drill": "Mechanical Drill", + "block.create.portable_storage_interface": "Portable Storage Interface", "block.create.harvester": "Mechanical Harvester", "block.create.saw": "Mechanical Saw", "block.create.water_wheel": "Water Wheel", diff --git a/src/main/resources/assets/create/models/block/portable_storage_interface.json b/src/main/resources/assets/create/models/block/portable_storage_interface.json new file mode 100644 index 000000000..177bbe7e6 --- /dev/null +++ b/src/main/resources/assets/create/models/block/portable_storage_interface.json @@ -0,0 +1,165 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "create:block/brass_casing", + "5": "create:block/andesite_casing_short", + "6": "create:block/gearbox_top", + "7": "block/dark_oak_log", + "1_2": "create:block/transposer", + "particle": "create:block/extractor" + }, + "elements": [ + { + "name": "Center", + "from": [2, 1, 2], + "to": [14, 11, 14], + "faces": { + "up": {"uv": [2, 4, 14, 16], "texture": "#7"}, + "down": {"uv": [2, 2, 14, 14], "texture": "#6"} + } + }, + { + "name": "Side", + "from": [0, 0, 0], + "to": [2, 12, 16], + "faces": { + "north": {"uv": [14, 4, 16, 16], "texture": "#5"}, + "east": {"uv": [0, 4, 16, 16], "texture": "#5"}, + "south": {"uv": [0, 4, 2, 16], "texture": "#5"}, + "west": {"uv": [0, 4, 16, 16], "texture": "#5"}, + "up": {"uv": [0, 0, 2, 16], "texture": "#6"}, + "down": {"uv": [0, 0, 2, 16], "texture": "#6"} + } + }, + { + "name": "Side", + "from": [14, 0, 0], + "to": [16, 12, 16], + "faces": { + "north": {"uv": [0, 4, 2, 16], "texture": "#5"}, + "east": {"uv": [0, 4, 16, 16], "texture": "#5"}, + "south": {"uv": [14, 4, 16, 16], "texture": "#5"}, + "west": {"uv": [0, 4, 16, 16], "texture": "#5"}, + "up": {"uv": [14, 0, 16, 16], "texture": "#6"}, + "down": {"uv": [14, 0, 16, 16], "texture": "#6"} + } + }, + { + "name": "Short Side", + "from": [2, 0, 0], + "to": [14, 12, 2], + "faces": { + "north": {"uv": [2, 4, 14, 16], "texture": "#5"}, + "south": {"uv": [2, 4, 14, 16], "texture": "#5"}, + "up": {"uv": [2, 0, 14, 2], "texture": "#6"}, + "down": {"uv": [2, 14, 14, 16], "texture": "#6"} + } + }, + { + "name": "Short Side", + "from": [2, 0, 14], + "to": [14, 12, 16], + "faces": { + "north": {"uv": [2, 4, 14, 16], "texture": "#5"}, + "south": {"uv": [2, 4, 14, 16], "texture": "#5"}, + "up": {"uv": [2, 14, 14, 16], "texture": "#6"}, + "down": {"uv": [2, 0, 14, 2], "texture": "#6"} + } + }, + { + "from": [4, 11, 4], + "to": [12, 15, 12], + "faces": { + "north": {"uv": [1, 4, 5, 12], "rotation": 90, "texture": "#0"}, + "east": {"uv": [1, 4, 5, 12], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1, 4, 5, 12], "rotation": 90, "texture": "#0"}, + "west": {"uv": [1, 4, 5, 12], "rotation": 90, "texture": "#0"}, + "up": {"uv": [7, 7, 15, 15], "rotation": 90, "texture": "#1_2"} + } + }, + { + "from": [3, 11, 11], + "to": [5, 16, 13], + "faces": { + "north": {"uv": [0, 14, 5, 16], "rotation": 90, "texture": "#0"}, + "east": {"uv": [11, 14, 16, 16], "rotation": 270, "texture": "#1_2"}, + "south": {"uv": [6, 14, 11, 16], "rotation": 90, "texture": "#1_2"}, + "west": {"uv": [6, 6, 11, 8], "rotation": 90, "texture": "#1_2"}, + "up": {"uv": [4, 6, 6, 8], "rotation": 180, "texture": "#1_2"} + } + }, + { + "from": [11, 11, 11], + "to": [13, 16, 13], + "faces": { + "north": {"uv": [0, 16, 5, 14], "rotation": 90, "texture": "#0"}, + "east": {"uv": [11, 6, 6, 8], "rotation": 270, "texture": "#1_2"}, + "south": {"uv": [6, 16, 11, 14], "rotation": 90, "texture": "#1_2"}, + "west": {"uv": [16, 14, 11, 16], "rotation": 90, "texture": "#1_2"}, + "up": {"uv": [6, 6, 4, 8], "rotation": 180, "texture": "#1_2"} + } + }, + { + "from": [3, 11, 3], + "to": [5, 16, 5], + "faces": { + "north": {"uv": [11, 14, 6, 16], "rotation": 270, "texture": "#1_2"}, + "east": {"uv": [11, 16, 16, 14], "rotation": 270, "texture": "#1_2"}, + "south": {"uv": [5, 14, 0, 16], "rotation": 270, "texture": "#0"}, + "west": {"uv": [6, 8, 11, 6], "rotation": 90, "texture": "#1_2"}, + "up": {"uv": [4, 8, 6, 6], "rotation": 180, "texture": "#1_2"} + } + }, + { + "from": [11, 11, 3], + "to": [13, 16, 5], + "faces": { + "north": {"uv": [11, 16, 6, 14], "rotation": 270, "texture": "#1_2"}, + "east": {"uv": [11, 8, 6, 6], "rotation": 270, "texture": "#1_2"}, + "south": {"uv": [5, 16, 0, 14], "rotation": 270, "texture": "#0"}, + "west": {"uv": [16, 16, 11, 14], "rotation": 90, "texture": "#1_2"}, + "up": {"uv": [6, 8, 4, 6], "rotation": 180, "texture": "#1_2"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "thirdperson_lefthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "firstperson_righthand": { + "rotation": [0, 45, 0], + "scale": [0.4, 0.4, 0.4] + }, + "firstperson_lefthand": { + "rotation": [0, 225, 0], + "scale": [0.4, 0.4, 0.4] + }, + "ground": { + "translation": [0, 3, 0], + "scale": [0.25, 0.25, 0.25] + }, + "gui": { + "rotation": [30, -45, -90], + "scale": [0.625, 0.625, 0.625] + }, + "fixed": { + "rotation": [-90, 0, 0], + "scale": [0.5, 0.5, 0.5] + } + }, + "groups": [ + { + "name": "group", + "origin": [8, 8, 8], + "children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/goggles.json b/src/main/resources/assets/create/models/item/goggles.json index 3883d0769..5dbe10332 100644 --- a/src/main/resources/assets/create/models/item/goggles.json +++ b/src/main/resources/assets/create/models/item/goggles.json @@ -3,7 +3,7 @@ "parent": "block/block", "textures": { "0": "create:block/brass_casing", - "1": "create:block/black_stained_glass", + "1": "block/black_stained_glass", "2": "create:item/goggles", "particle": "create:block/brass_casing" }, diff --git a/src/main/resources/assets/create/models/item/portable_storage_interface.json b/src/main/resources/assets/create/models/item/portable_storage_interface.json new file mode 100644 index 000000000..b2d60596c --- /dev/null +++ b/src/main/resources/assets/create/models/item/portable_storage_interface.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/portable_storage_interface" +} \ No newline at end of file diff --git a/src/main/resources/assets/create/textures/block/bearing_side.png b/src/main/resources/assets/create/textures/block/bearing_side.png index 2dc4d8d67..c9bd01598 100644 Binary files a/src/main/resources/assets/create/textures/block/bearing_side.png and b/src/main/resources/assets/create/textures/block/bearing_side.png differ diff --git a/src/main/resources/assets/create/textures/block/transposer.png b/src/main/resources/assets/create/textures/block/transposer.png index fade062c2..056e2a6f0 100644 Binary files a/src/main/resources/assets/create/textures/block/transposer.png and b/src/main/resources/assets/create/textures/block/transposer.png differ diff --git a/src/main/resources/data/create/loot_tables/blocks/portable_storage_interface.json b/src/main/resources/data/create/loot_tables/blocks/portable_storage_interface.json new file mode 100644 index 000000000..db6214adf --- /dev/null +++ b/src/main/resources/data/create/loot_tables/blocks/portable_storage_interface.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:portable_storage_interface" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file