mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-23 21:46:40 +01:00
Pulse Repeaters, Belt Funnels and working Fans
- Added the Pulse Repeater, a simple Pulse former circuit. - Added a Belt Funnel, along with a generic belt attachment interface. - Fans now push or pull entities based on their rotation speed. - Added little symbols to extractor and funnel item models
This commit is contained in:
parent
12baa08232
commit
ebaf22ddcc
31 changed files with 1461 additions and 94 deletions
|
@ -17,7 +17,6 @@ import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalP
|
|||
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonHeadBlock;
|
||||
import com.simibubi.create.modules.contraptions.receivers.constructs.PistonPoleBlock;
|
||||
import com.simibubi.create.modules.contraptions.redstone.ContactBlock;
|
||||
import com.simibubi.create.modules.contraptions.relays.BeltBlock;
|
||||
import com.simibubi.create.modules.contraptions.relays.ClutchBlock;
|
||||
import com.simibubi.create.modules.contraptions.relays.CogWheelBlock;
|
||||
import com.simibubi.create.modules.contraptions.relays.EncasedBeltBlock;
|
||||
|
@ -26,11 +25,14 @@ import com.simibubi.create.modules.contraptions.relays.GearboxBlock;
|
|||
import com.simibubi.create.modules.contraptions.relays.GearshiftBlock;
|
||||
import com.simibubi.create.modules.contraptions.relays.ShaftBlock;
|
||||
import com.simibubi.create.modules.contraptions.relays.ShaftHalfBlock;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
|
||||
import com.simibubi.create.modules.economy.ShopShelfBlock;
|
||||
import com.simibubi.create.modules.gardens.CocoaLogBlock;
|
||||
import com.simibubi.create.modules.logistics.block.BeltFunnelBlock;
|
||||
import com.simibubi.create.modules.logistics.block.ExtractorBlock;
|
||||
import com.simibubi.create.modules.logistics.block.FlexcrateBlock;
|
||||
import com.simibubi.create.modules.logistics.block.LinkedExtractorBlock;
|
||||
import com.simibubi.create.modules.logistics.block.PulseRepeaterBlock;
|
||||
import com.simibubi.create.modules.logistics.block.RedstoneBridgeBlock;
|
||||
import com.simibubi.create.modules.logistics.block.StockswitchBlock;
|
||||
import com.simibubi.create.modules.schematics.block.CreativeCrateBlock;
|
||||
|
@ -98,11 +100,13 @@ public enum AllBlocks {
|
|||
CONTACT(new ContactBlock()),
|
||||
|
||||
// Logistics
|
||||
PULSE_REPEATER(new PulseRepeaterBlock()),
|
||||
REDSTONE_BRIDGE(new RedstoneBridgeBlock()),
|
||||
STOCKSWITCH(new StockswitchBlock()),
|
||||
FLEXCRATE(new FlexcrateBlock()),
|
||||
EXTRACTOR(new ExtractorBlock()),
|
||||
LINKED_EXTRACTOR(new LinkedExtractorBlock()),
|
||||
BELT_FUNNEL(new BeltFunnelBlock()),
|
||||
|
||||
// Symmetry
|
||||
SYMMETRY_PLANE(new PlaneSymmetryBlock()),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.simibubi.create;
|
||||
|
||||
import com.simibubi.create.modules.contraptions.relays.BeltItem;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltItem;
|
||||
import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunItem;
|
||||
import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunItemRenderer;
|
||||
import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunModel;
|
||||
|
|
|
@ -14,17 +14,18 @@ import com.simibubi.create.modules.contraptions.receivers.EncasedFanTileEntityRe
|
|||
import com.simibubi.create.modules.contraptions.receivers.TurntableTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonTileEntityRenderer;
|
||||
import com.simibubi.create.modules.contraptions.relays.ShaftTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.ClutchTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.EncasedShaftTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.EncasedShaftTileEntityRenderer;
|
||||
import com.simibubi.create.modules.contraptions.relays.BeltTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.BeltTileEntityRenderer;
|
||||
import com.simibubi.create.modules.contraptions.relays.ClutchTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.GearboxTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.GearboxTileEntityRenderer;
|
||||
import com.simibubi.create.modules.contraptions.relays.GearshiftTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.ShaftTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.SplitShaftTileEntityRenderer;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntityRenderer;
|
||||
import com.simibubi.create.modules.economy.ShopShelfTileEntity;
|
||||
import com.simibubi.create.modules.logistics.block.BeltFunnelTileEntity;
|
||||
import com.simibubi.create.modules.logistics.block.ExtractorTileEntity;
|
||||
import com.simibubi.create.modules.logistics.block.FlexcrateTileEntity;
|
||||
import com.simibubi.create.modules.logistics.block.LinkedExtractorTileEntity;
|
||||
|
@ -73,8 +74,10 @@ public enum AllTileEntities {
|
|||
// Logistics
|
||||
REDSTONE_BRIDGE(RedstoneBridgeTileEntity::new, AllBlocks.REDSTONE_BRIDGE),
|
||||
STOCKSWITCH(StockswitchTileEntity::new, AllBlocks.STOCKSWITCH),
|
||||
FLEXCRATE(FlexcrateTileEntity::new, AllBlocks.FLEXCRATE), EXTRACTOR(ExtractorTileEntity::new, AllBlocks.EXTRACTOR),
|
||||
FLEXCRATE(FlexcrateTileEntity::new, AllBlocks.FLEXCRATE),
|
||||
EXTRACTOR(ExtractorTileEntity::new, AllBlocks.EXTRACTOR),
|
||||
LINKED_EXTRACTOR(LinkedExtractorTileEntity::new, AllBlocks.LINKED_EXTRACTOR),
|
||||
BELT_FUNNEL(BeltFunnelTileEntity::new, AllBlocks.BELT_FUNNEL),
|
||||
|
||||
// Economy
|
||||
SHOP_SHELF(ShopShelfTileEntity::new, AllBlocks.SHOP_SHELF),
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package com.simibubi.create.foundation.block;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorld;
|
||||
|
||||
public interface IWithTileEntity<T extends TileEntity> {
|
||||
|
||||
default void withTileEntityDo(IWorld world, BlockPos pos, Consumer<T> action) {
|
||||
@SuppressWarnings("unchecked")
|
||||
T te = (T) world.getTileEntity(pos);
|
||||
if (te == null)
|
||||
return;
|
||||
action.accept(te);
|
||||
}
|
||||
|
||||
}
|
|
@ -6,10 +6,10 @@ import java.util.List;
|
|||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.modules.contraptions.base.IRotate;
|
||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.BeltTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.EncasedBeltBlock;
|
||||
import com.simibubi.create.modules.contraptions.relays.GearboxTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.SplitShaftTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.state.IProperty;
|
||||
|
@ -66,6 +66,12 @@ public class RotationPropagator {
|
|||
&& stateTo.get(EncasedBeltBlock.CONNECTED_FACE) == direction.getOpposite();
|
||||
return connected ? 1 : 0;
|
||||
}
|
||||
|
||||
// Attached Fans
|
||||
if (AllBlocks.ENCASED_FAN.typeOf(stateFrom) && AllBlocks.ENCASED_FAN.typeOf(stateTo)) {
|
||||
if (stateFrom.get(BlockStateProperties.AXIS) == stateTo.get(BlockStateProperties.AXIS))
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Gear <-> Large Gear
|
||||
if (isLargeToSmallGear(stateFrom, stateTo, diff))
|
||||
|
|
|
@ -34,13 +34,6 @@ public abstract class KineticTileEntity extends SyncedTileEntity {
|
|||
public void onSpeedChanged() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
if (!hasWorld())
|
||||
return;
|
||||
super.onLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (world.isRemote) {
|
||||
|
|
|
@ -47,12 +47,6 @@ public class WaterWheelTileEntity extends KineticTileEntity {
|
|||
flows.put(direction, speed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
super.onLoad();
|
||||
// updateSpeed();
|
||||
}
|
||||
|
||||
public void updateSpeed() {
|
||||
float speed = 0;
|
||||
for (Integer i : flows.values())
|
||||
|
|
|
@ -1,29 +1,70 @@
|
|||
package com.simibubi.create.modules.contraptions.receivers;
|
||||
|
||||
import com.simibubi.create.foundation.block.IWithTileEntity;
|
||||
import com.simibubi.create.foundation.utility.ItemDescription;
|
||||
import com.simibubi.create.modules.contraptions.relays.EncasedShaftBlock;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
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.world.IBlockReader;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EncasedFanBlock extends EncasedShaftBlock {
|
||||
public class EncasedFanBlock extends EncasedShaftBlock implements IWithTileEntity<EncasedFanTileEntity> {
|
||||
|
||||
@Override
|
||||
public ItemDescription getDescription() {
|
||||
return new ItemDescription(color)
|
||||
.withSummary("Exchange rotational power for air flow and back.").createTabs();
|
||||
return new ItemDescription(color).withSummary("Exchange rotational power for air flow and back.").createTabs();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
||||
return new EncasedFanTileEntity();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
|
||||
Axis axisIn = state.get(AXIS);
|
||||
notifyFanTile(worldIn, pos, Direction.getFacingFromAxisDirection(axisIn, AxisDirection.POSITIVE));
|
||||
notifyFanTile(worldIn, pos, Direction.getFacingFromAxisDirection(axisIn, AxisDirection.NEGATIVE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
|
||||
boolean isMoving) {
|
||||
Axis axisIn = state.get(AXIS);
|
||||
notifyFanTile(worldIn, pos, Direction.getFacingFromAxisDirection(axisIn, AxisDirection.POSITIVE));
|
||||
notifyFanTile(worldIn, pos, Direction.getFacingFromAxisDirection(axisIn, AxisDirection.NEGATIVE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn,
|
||||
BlockPos currentPos, BlockPos facingPos) {
|
||||
if (facing.getAxis() == stateIn.get(AXIS))
|
||||
notifyFanTile(worldIn, currentPos, facing);
|
||||
return stateIn;
|
||||
}
|
||||
|
||||
protected void notifyFanTile(IWorld world, BlockPos pos, Direction facing) {
|
||||
withTileEntityDo(world, pos, te -> te.setNeighbour(facing, world.getBlockState(pos.offset(facing))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockRenderLayer getRenderLayer() {
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
|
||||
public static boolean canAirPassThrough(World world, BlockPos pos, Direction direction) {
|
||||
if (!world.isBlockPresent(pos))
|
||||
return true;
|
||||
BlockState state = world.getBlockState(pos);
|
||||
return !Block.hasSolidSide(state, world, pos, direction.getOpposite());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,400 @@
|
|||
package com.simibubi.create.modules.contraptions.receivers;
|
||||
|
||||
import static net.minecraft.state.properties.BlockStateProperties.AXIS;
|
||||
import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
|
||||
import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||
|
||||
public class EncasedFanTileEntity extends KineticTileEntity {
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.INBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.particles.BlockParticleData;
|
||||
import net.minecraft.particles.IParticleData;
|
||||
import net.minecraft.particles.ParticleTypes;
|
||||
import net.minecraft.particles.RedstoneParticleData;
|
||||
import net.minecraft.tileentity.ITickableTileEntity;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
|
||||
public class EncasedFanTileEntity extends KineticTileEntity implements ITickableTileEntity {
|
||||
|
||||
public static final int PUSH_DISTANCE_MAX = 20;
|
||||
public static final int PULL_DISTANCE_MAX = 5;
|
||||
public static final int DISTANCE_ARGMAX = 6400;
|
||||
|
||||
public static final float PUSH_FORCE_MAX = 20;
|
||||
public static final float PULL_FORCE_MAX = 10;
|
||||
public static final int FORCE_ARGMAX = 6400;
|
||||
|
||||
public static final int BLOCK_CHECK_UPDATE_DELAY = 100;
|
||||
public static final Map<Block, List<FanEffect>> effects = new HashMap<>();
|
||||
|
||||
private static DamageSource damageSourceFire = new DamageSource("create.fan_fire").setDifficultyScaled()
|
||||
.setFireDamage();
|
||||
private static DamageSource damageSourceLava = new DamageSource("create.fan_lava").setDifficultyScaled()
|
||||
.setFireDamage();
|
||||
|
||||
protected BlockState frontBlock;
|
||||
protected BlockState backBlock;
|
||||
protected float pushDistance;
|
||||
protected float pullDistance;
|
||||
protected float pushForce;
|
||||
protected float pullForce;
|
||||
protected AxisAlignedBB frontBB;
|
||||
protected AxisAlignedBB backBB;
|
||||
protected int blockCheckCooldown;
|
||||
protected boolean findLoadedItems;
|
||||
public List<ProcessedItem> items;
|
||||
|
||||
public class ProcessedItem {
|
||||
private UUID loadedUUID;
|
||||
private ItemEntity entity;
|
||||
private int processingTimeLeft;
|
||||
|
||||
public ProcessedItem(UUID uuid, int timeLeft) {
|
||||
loadedUUID = uuid;
|
||||
processingTimeLeft = timeLeft;
|
||||
}
|
||||
|
||||
public ProcessedItem(ItemEntity item) {
|
||||
entity = item;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class FanEffect {
|
||||
private IParticleData particle;
|
||||
private float density;
|
||||
private float chance;
|
||||
private float spread;
|
||||
private float speed;
|
||||
private Random r;
|
||||
|
||||
public FanEffect(IParticleData particle, float density, float chance, float spread, float speed) {
|
||||
r = new Random();
|
||||
this.particle = particle;
|
||||
this.density = density;
|
||||
this.chance = chance;
|
||||
this.spread = spread;
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
public void render(Vec3i directionVec, boolean front, EncasedFanTileEntity te) {
|
||||
render(directionVec, front ? .5f : -te.pullDistance, front ? te.pushDistance : -.5f, te);
|
||||
}
|
||||
|
||||
private void render(Vec3i directionVec, float start, float end, EncasedFanTileEntity te) {
|
||||
float x = directionVec.getX();
|
||||
float y = directionVec.getY();
|
||||
float z = directionVec.getZ();
|
||||
float speed = this.speed * Math.abs(te.speed) / 512f;
|
||||
|
||||
for (float offset = start; offset < end; offset += density) {
|
||||
if (r.nextFloat() > chance)
|
||||
continue;
|
||||
float xs = rollOffset() * spread;
|
||||
float ys = rollOffset() * spread;
|
||||
float zs = rollOffset() * spread;
|
||||
float xs2 = rollOffset() * spread;
|
||||
float ys2 = rollOffset() * spread;
|
||||
float zs2 = rollOffset() * spread;
|
||||
te.world.addParticle(particle, te.pos.getX() + .5f + x * offset + xs2,
|
||||
te.pos.getY() + .5f + y * offset + ys2, te.pos.getZ() + .5f + z * offset + zs2, x * speed + xs,
|
||||
y * speed + ys, z * speed + zs);
|
||||
}
|
||||
}
|
||||
|
||||
private float rollOffset() {
|
||||
return (r.nextFloat() - .5f) * 2;
|
||||
}
|
||||
}
|
||||
|
||||
public EncasedFanTileEntity() {
|
||||
super(AllTileEntities.ENCASED_FAN.type);
|
||||
blockCheckCooldown = BLOCK_CHECK_UPDATE_DELAY;
|
||||
frontBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
|
||||
backBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
|
||||
items = new ArrayList<>();
|
||||
if (effects.isEmpty())
|
||||
initEffects();
|
||||
}
|
||||
|
||||
private static void initEffects() {
|
||||
effects.clear();
|
||||
|
||||
List<FanEffect> standardFX = new ArrayList<>(2);
|
||||
standardFX.add(new FanEffect(ParticleTypes.BUBBLE_POP, 1 / 4f, 1 / 8f, 1 / 8f, 1));
|
||||
standardFX.add(new FanEffect(new RedstoneParticleData(1, 1, 1, 1), 1 / 2f, 1 / 32f, 0f, 512f));
|
||||
effects.put(Blocks.AIR, standardFX);
|
||||
|
||||
List<FanEffect> waterFX = new ArrayList<>(2);
|
||||
waterFX.add(new FanEffect(new BlockParticleData(ParticleTypes.BLOCK, Blocks.WATER.getDefaultState()), 1 / 4f,
|
||||
1 / 2f, 1 / 4f, 1));
|
||||
waterFX.add(new FanEffect(ParticleTypes.SPLASH, 1 / 4f, 1 / 2f, 0.5f, 1));
|
||||
effects.put(Blocks.WATER, waterFX);
|
||||
|
||||
List<FanEffect> fireFX = new ArrayList<>(2);
|
||||
fireFX.add(new FanEffect(ParticleTypes.LARGE_SMOKE, 1 / 4f, 1 / 8f, 0.125f, .5f));
|
||||
fireFX.add(new FanEffect(ParticleTypes.FLAME, 1 / 4f, 1 / 8f, 1 / 32f, 1 / 256f));
|
||||
effects.put(Blocks.FIRE, fireFX);
|
||||
|
||||
List<FanEffect> lavaFX = new ArrayList<>(3);
|
||||
lavaFX.add(new FanEffect(new BlockParticleData(ParticleTypes.BLOCK, Blocks.LAVA.getDefaultState()), 1 / 4f,
|
||||
1 / 2f, 1 / 4f, 1));
|
||||
lavaFX.add(new FanEffect(ParticleTypes.LAVA, 1 / 2f, 1 / 32f, 0, .25f));
|
||||
lavaFX.add(new FanEffect(ParticleTypes.FLAME, 1 / 4f, 1 / 32f, 1 / 32f, 1 / 256f));
|
||||
effects.put(Blocks.LAVA, lavaFX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
super.readClientUpdate(tag);
|
||||
pushDistance = tag.getFloat("PushDistance");
|
||||
pullDistance = tag.getFloat("PullDistance");
|
||||
pushForce = tag.getFloat("PushForce");
|
||||
pullForce = tag.getFloat("PullForce");
|
||||
updateBothNeighbours();
|
||||
updateBBs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT writeToClient(CompoundNBT tag) {
|
||||
super.writeToClient(tag);
|
||||
tag.putFloat("PushDistance", pushDistance);
|
||||
tag.putFloat("PullDistance", pullDistance);
|
||||
tag.putFloat("PushForce", pushForce);
|
||||
tag.putFloat("PullForce", pullForce);
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
blockCheckCooldown = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
super.read(compound);
|
||||
ListNBT itemsNBT = compound.getList("Items", 10);
|
||||
items.clear();
|
||||
for (INBT iNBT : itemsNBT) {
|
||||
CompoundNBT itemNBT = (CompoundNBT) iNBT;
|
||||
items.add(new ProcessedItem(NBTUtil.readUniqueId(itemNBT.getCompound("UUID")), itemNBT.getInt("TimeLeft")));
|
||||
}
|
||||
findLoadedItems = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
ListNBT itemsNBT = new ListNBT();
|
||||
for (ProcessedItem item : items) {
|
||||
CompoundNBT itemNBT = new CompoundNBT();
|
||||
itemNBT.put("UUID", NBTUtil.writeUniqueId(item.entity.getUniqueID()));
|
||||
itemNBT.putInt("TimeLeft", item.processingTimeLeft);
|
||||
itemsNBT.add(itemNBT);
|
||||
}
|
||||
compound.put("Items", itemsNBT);
|
||||
return super.write(compound);
|
||||
}
|
||||
|
||||
protected void updateReachAndForce() {
|
||||
if (getWorld() == null)
|
||||
return;
|
||||
if (world.isRemote)
|
||||
return;
|
||||
|
||||
float speed = Math.abs(this.speed);
|
||||
float distanceFactor = Math.min(speed / DISTANCE_ARGMAX, 1);
|
||||
float forceFactor = Math.min(speed / FORCE_ARGMAX, 1);
|
||||
|
||||
pushDistance = MathHelper.lerp(distanceFactor, 3, PUSH_DISTANCE_MAX);
|
||||
pullDistance = MathHelper.lerp(distanceFactor, 1.5f, PULL_DISTANCE_MAX);
|
||||
pushForce = MathHelper.lerp(forceFactor, 1, PUSH_FORCE_MAX);
|
||||
pullForce = MathHelper.lerp(forceFactor, 1, PULL_FORCE_MAX);
|
||||
|
||||
Direction direction = getAirFlow();
|
||||
if (speed != 0) {
|
||||
for (int distance = 1; distance <= pushDistance; distance++) {
|
||||
if (!EncasedFanBlock.canAirPassThrough(world, getPos().offset(direction, distance), direction)) {
|
||||
pushDistance = distance - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int distance = 1; distance <= pullDistance; distance++) {
|
||||
if (!EncasedFanBlock.canAirPassThrough(world, getPos().offset(direction, -distance), direction)) {
|
||||
pullDistance = distance - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateBBs();
|
||||
} else {
|
||||
frontBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
|
||||
backBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
sendData();
|
||||
}
|
||||
|
||||
protected void updateBBs() {
|
||||
Direction flow = getAirFlow();
|
||||
if (flow == null)
|
||||
return;
|
||||
Vec3i flowVec = flow.getDirectionVec();
|
||||
float remainder = pushDistance - (int) pushDistance;
|
||||
frontBB = new AxisAlignedBB(pos.offset(flow), pos.offset(flow, (int) pushDistance))
|
||||
.expand(flowVec.getX() * remainder + 1, flowVec.getY() * remainder + 1, flowVec.getZ() * remainder + 1)
|
||||
.grow(.25f);
|
||||
remainder = pullDistance - (int) pullDistance;
|
||||
backBB = new AxisAlignedBB(pos.offset(flow, -(int) pullDistance), pos.offset(flow, -1))
|
||||
.expand(-flowVec.getX() * remainder + 1, -flowVec.getY() * remainder + 1,
|
||||
-flowVec.getZ() * remainder + 1)
|
||||
.grow(.25f);
|
||||
}
|
||||
|
||||
public void updateBothNeighbours() {
|
||||
Axis axis = getBlockState().get(AXIS);
|
||||
Direction frontFacing = Direction.getFacingFromAxis(POSITIVE, axis);
|
||||
Direction backFacing = Direction.getFacingFromAxis(NEGATIVE, axis);
|
||||
BlockPos front = pos.offset(frontFacing);
|
||||
BlockPos back = pos.offset(backFacing);
|
||||
if (world.isBlockPresent(front))
|
||||
setNeighbour(frontFacing, world.getBlockState(front));
|
||||
if (world.isBlockPresent(back))
|
||||
setNeighbour(backFacing, world.getBlockState(back));
|
||||
}
|
||||
|
||||
public void setNeighbour(Direction direction, BlockState neighbourState) {
|
||||
if (direction.getAxisDirection() == NEGATIVE)
|
||||
backBlock = neighbourState;
|
||||
else
|
||||
frontBlock = neighbourState;
|
||||
updateReachAndForce();
|
||||
}
|
||||
|
||||
public Direction getAirFlow() {
|
||||
if (speed == 0)
|
||||
return null;
|
||||
return Direction.getFacingFromAxisDirection(getBlockState().get(AXIS), speed > 0 ? POSITIVE : NEGATIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpeedChanged() {
|
||||
updateReachAndForce();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (speed == 0)
|
||||
return;
|
||||
|
||||
List<Entity> frontEntities = world.getEntitiesWithinAABBExcludingEntity(null, frontBB);
|
||||
for (Entity entity : frontEntities) {
|
||||
moveEntity(entity, true);
|
||||
if (!(entity instanceof ItemEntity)) {
|
||||
if (frontBlock != null && frontBlock.getBlock() == Blocks.FIRE) {
|
||||
entity.setFire(2);
|
||||
entity.attackEntityFrom(damageSourceFire, 4);
|
||||
}
|
||||
if (frontBlock != null && frontBlock.getBlock() == Blocks.LAVA) {
|
||||
entity.setFire(10);
|
||||
entity.attackEntityFrom(damageSourceLava, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, backBB)) {
|
||||
moveEntity(entity, false);
|
||||
}
|
||||
|
||||
if (world.isRemote) {
|
||||
makeParticles();
|
||||
return;
|
||||
}
|
||||
|
||||
if (blockCheckCooldown-- <= 0) {
|
||||
blockCheckCooldown = BLOCK_CHECK_UPDATE_DELAY;
|
||||
updateReachAndForce();
|
||||
}
|
||||
|
||||
if (findLoadedItems) {
|
||||
findLoadedItems = false;
|
||||
for (ProcessedItem item : items) {
|
||||
for (Entity entity : frontEntities) {
|
||||
if (!(entity instanceof ItemEntity))
|
||||
continue;
|
||||
if (entity.getUniqueID().equals(item.loadedUUID))
|
||||
item.entity = (ItemEntity) entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void moveEntity(Entity entity, boolean push) {
|
||||
if ((entity instanceof ItemEntity) && AllBlocks.BELT.typeOf(world.getBlockState(entity.getPosition()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3d center = VecHelper.getCenterOf(pos);
|
||||
Vec3i flow = getAirFlow().getDirectionVec();
|
||||
float modifier = entity.isSneaking() ? 4096f : 512f;
|
||||
float s = (float) (speed * 1 / modifier
|
||||
/ (entity.getPositionVec().distanceTo(center) / (push ? pushDistance : pullDistance)));
|
||||
Vec3d motion = entity.getMotion();
|
||||
double xIn = flow.getX() * s - motion.x;
|
||||
double yIn = flow.getY() * s - motion.y;
|
||||
double zIn = flow.getZ() * s - motion.z;
|
||||
entity.setMotion(motion.add(new Vec3d(xIn, yIn, zIn).mul(flow.getX(), flow.getY(), flow.getZ()).scale(1 / 8f)));
|
||||
entity.fallDistance = 0;
|
||||
}
|
||||
|
||||
protected void makeParticles() {
|
||||
Direction direction = getAirFlow();
|
||||
Vec3i directionVec = direction.getDirectionVec();
|
||||
|
||||
boolean hasFx = false;
|
||||
if (frontBlock != null) {
|
||||
if (effects.containsKey(frontBlock.getBlock())) {
|
||||
hasFx = true;
|
||||
for (FanEffect fx : effects.get(frontBlock.getBlock()))
|
||||
fx.render(directionVec, true, this);
|
||||
}
|
||||
}
|
||||
if (backBlock != null && !hasFx) {
|
||||
if (effects.containsKey(backBlock.getBlock())) {
|
||||
hasFx = true;
|
||||
for (FanEffect fx : effects.get(backBlock.getBlock()))
|
||||
fx.render(directionVec, true, this);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasFx)
|
||||
for (FanEffect fx : effects.get(Blocks.AIR))
|
||||
fx.render(directionVec, true, this);
|
||||
|
||||
for (FanEffect fx : effects.get(Blocks.AIR))
|
||||
fx.render(directionVec, false, this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.INBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorld;
|
||||
|
||||
public enum AllBeltAttachments {
|
||||
|
||||
BELT_FUNNEL(AllBlocks.BELT_FUNNEL),
|
||||
|
||||
;
|
||||
|
||||
IBeltAttachment attachment;
|
||||
|
||||
private AllBeltAttachments(AllBlocks attachment) {
|
||||
this.attachment = (IBeltAttachment) attachment.get();
|
||||
}
|
||||
|
||||
public interface IBeltAttachment {
|
||||
public Optional<BlockPos> getValidAttachmentFor(BeltTileEntity te);
|
||||
|
||||
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state);
|
||||
|
||||
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state);
|
||||
|
||||
default void onAttachmentPlaced(IWorld world, BlockPos pos, BlockState state) {
|
||||
Optional<BlockPos> beltPos = getValidBeltPositionFor(world, pos, state);
|
||||
if (!beltPos.isPresent())
|
||||
return;
|
||||
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(beltPos.get());
|
||||
if (te == null)
|
||||
return;
|
||||
te.attachmentTracker.addAttachment(world, pos);
|
||||
te.sendData();
|
||||
}
|
||||
|
||||
default void onAttachmentRemoved(IWorld world, BlockPos pos, BlockState state) {
|
||||
Optional<BlockPos> beltPos = getValidBeltPositionFor(world, pos, state);
|
||||
if (!beltPos.isPresent())
|
||||
return;
|
||||
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(beltPos.get());
|
||||
if (te == null)
|
||||
return;
|
||||
te.attachmentTracker.removeAttachment(pos);
|
||||
te.sendData();
|
||||
}
|
||||
}
|
||||
|
||||
public static class BeltAttachmentState {
|
||||
public IBeltAttachment attachment;
|
||||
public BlockPos attachmentPos;
|
||||
public int processingDuration;
|
||||
public Entity processingEntity;
|
||||
|
||||
public BeltAttachmentState(IBeltAttachment attachment, BlockPos attachmentPos) {
|
||||
this.attachment = attachment;
|
||||
this.attachmentPos = attachmentPos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Tracker {
|
||||
public List<BeltAttachmentState> attachments;
|
||||
|
||||
public Tracker() {
|
||||
attachments = new ArrayList<>(0);
|
||||
}
|
||||
|
||||
public void findAttachments(BeltTileEntity belt) {
|
||||
for (AllBeltAttachments ba : AllBeltAttachments.values()) {
|
||||
Optional<BlockPos> validAttachmentFor = ba.attachment.getValidAttachmentFor(belt);
|
||||
if (validAttachmentFor.isPresent()) {
|
||||
BlockPos pos = validAttachmentFor.get();
|
||||
addAttachment(belt.getWorld(), pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BeltAttachmentState addAttachment(IWorld world, BlockPos pos) {
|
||||
BlockState state = world.getBlockState(pos);
|
||||
removeAttachment(pos);
|
||||
BeltAttachmentState newAttachmentState = new BeltAttachmentState((IBeltAttachment) state.getBlock(), pos);
|
||||
attachments.add(newAttachmentState);
|
||||
return newAttachmentState;
|
||||
}
|
||||
|
||||
public void removeAttachment(BlockPos pos) {
|
||||
BeltAttachmentState toRemove = null;
|
||||
for (BeltAttachmentState atState : attachments)
|
||||
if (atState.attachmentPos.equals(pos))
|
||||
toRemove = atState;
|
||||
if (toRemove != null)
|
||||
attachments.remove(toRemove);
|
||||
}
|
||||
|
||||
public void forEachAttachment(Consumer<BeltAttachmentState> consumer) {
|
||||
attachments.forEach(consumer::accept);
|
||||
}
|
||||
|
||||
public void readAndSearch(CompoundNBT nbt, BeltTileEntity belt) {
|
||||
attachments.clear();
|
||||
if (!nbt.contains("HasAttachments"))
|
||||
return;
|
||||
if (nbt.contains("AttachmentData")) {
|
||||
ListNBT list = (ListNBT) nbt.get("AttachmentData");
|
||||
for (INBT data : list) {
|
||||
CompoundNBT stateNBT = (CompoundNBT) data;
|
||||
BlockPos attachmentPos = NBTUtil.readBlockPos(stateNBT.getCompound("Position"));
|
||||
BeltAttachmentState atState = addAttachment(belt.getWorld(), attachmentPos);
|
||||
atState.processingDuration = stateNBT.getInt("Duration");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write(CompoundNBT nbt) {
|
||||
if (!attachments.isEmpty()) {
|
||||
nbt.putBoolean("HasAttachments", true);
|
||||
ListNBT list = new ListNBT();
|
||||
forEachAttachment(atState -> {
|
||||
CompoundNBT stateNBT = new CompoundNBT();
|
||||
stateNBT.put("Position", NBTUtil.writeBlockPos(atState.attachmentPos));
|
||||
stateNBT.putInt("Duration", atState.processingDuration);
|
||||
list.add(stateNBT);
|
||||
});
|
||||
nbt.put("AttachmentData", list);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +1,15 @@
|
|||
package com.simibubi.create.modules.contraptions.relays;
|
||||
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.foundation.block.IWithTileEntity;
|
||||
import com.simibubi.create.foundation.block.IWithoutBlockItem;
|
||||
import com.simibubi.create.foundation.utility.ItemDescription;
|
||||
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
|
||||
import com.simibubi.create.modules.contraptions.relays.BeltTileEntity.TransportedEntityInfo;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity.TransportedEntityInfo;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -36,7 +37,7 @@ import net.minecraft.world.IBlockReader;
|
|||
import net.minecraft.world.IWorldReader;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockItem {
|
||||
public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockItem, IWithTileEntity<BeltTileEntity> {
|
||||
|
||||
public static final IProperty<Slope> SLOPE = EnumProperty.create("slope", Slope.class);
|
||||
public static final IProperty<Part> PART = EnumProperty.create("part", Part.class);
|
||||
|
@ -103,6 +104,8 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
|
|||
|
||||
if (controller == null)
|
||||
return;
|
||||
if (controller.passengers == null)
|
||||
return;
|
||||
|
||||
if (controller.passengers.containsKey(entityIn))
|
||||
controller.passengers.get(entityIn).refresh(belt.getPos(), belt.getBlockState());
|
||||
|
@ -132,6 +135,8 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
|
|||
|
||||
if (controller == null)
|
||||
return;
|
||||
if (controller.passengers == null)
|
||||
return;
|
||||
|
||||
if (controller.passengers.containsKey(entityIn)) {
|
||||
TransportedEntityInfo transportedEntityInfo = controller.passengers.get(entityIn);
|
||||
|
@ -141,6 +146,13 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
|
|||
controller.passengers.put(entityIn, new TransportedEntityInfo(pos, state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
|
||||
withTileEntityDo(worldIn, pos, te -> {
|
||||
te.attachmentTracker.findAttachments(te);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillStateContainer(Builder<Block, BlockState> builder) {
|
||||
builder.add(SLOPE, PART);
|
|
@ -1,12 +1,12 @@
|
|||
package com.simibubi.create.modules.contraptions.relays;
|
||||
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.BeltBlock.Part;
|
||||
import com.simibubi.create.modules.contraptions.relays.BeltBlock.Slope;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.Item;
|
|
@ -1,4 +1,4 @@
|
|||
package com.simibubi.create.modules.contraptions.relays;
|
||||
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
|
@ -1,4 +1,4 @@
|
|||
package com.simibubi.create.modules.contraptions.relays;
|
||||
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -8,8 +8,10 @@ import java.util.Map;
|
|||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.relays.BeltBlock.Part;
|
||||
import com.simibubi.create.modules.contraptions.relays.BeltBlock.Slope;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.Tracker;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
|
@ -34,6 +36,8 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn
|
|||
|
||||
protected BlockPos controller;
|
||||
public Map<Entity, TransportedEntityInfo> passengers;
|
||||
public AllBeltAttachments.Tracker attachmentTracker;
|
||||
private CompoundNBT trackerUpdateTag;
|
||||
|
||||
protected static class TransportedEntityInfo {
|
||||
int ticksSinceLastCollision;
|
||||
|
@ -59,18 +63,37 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn
|
|||
public BeltTileEntity() {
|
||||
super(AllTileEntities.BELT.type);
|
||||
controller = BlockPos.ZERO;
|
||||
passengers = new HashMap<>();
|
||||
attachmentTracker = new Tracker();
|
||||
}
|
||||
|
||||
protected boolean isLastBelt() {
|
||||
if (speed == 0)
|
||||
return false;
|
||||
|
||||
Direction direction = getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
|
||||
if (getBlockState().get(BeltBlock.SLOPE) == Slope.VERTICAL)
|
||||
return false;
|
||||
|
||||
Part part = getBlockState().get(BeltBlock.PART);
|
||||
if (part == Part.MIDDLE)
|
||||
return false;
|
||||
|
||||
boolean movingPositively = (speed > 0 == (direction.getAxisDirection().getOffset() == 1))
|
||||
^ direction.getAxis() == Axis.X;
|
||||
return part == Part.START ^ movingPositively;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
compound.put("Controller", NBTUtil.writeBlockPos(controller));
|
||||
attachmentTracker.write(compound);
|
||||
return super.write(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
controller = NBTUtil.readBlockPos(compound.getCompound("Controller"));
|
||||
trackerUpdateTag = compound;
|
||||
super.read(compound);
|
||||
}
|
||||
|
||||
|
@ -94,8 +117,14 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn
|
|||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (world != null && trackerUpdateTag != null) {
|
||||
attachmentTracker.readAndSearch(trackerUpdateTag, this);
|
||||
trackerUpdateTag = null;
|
||||
}
|
||||
if (!isController())
|
||||
return;
|
||||
if (passengers == null)
|
||||
passengers = new HashMap<>();
|
||||
|
||||
passengers.forEach((entity, info) -> {
|
||||
transportEntity(entity, info);
|
||||
|
@ -110,7 +139,11 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn
|
|||
}
|
||||
info.tick();
|
||||
});
|
||||
toRemove.forEach(passengers::remove);
|
||||
toRemove.forEach(e -> {
|
||||
if (e instanceof ItemEntity)
|
||||
((ItemEntity) e).setAgeToCreativeDespawnTime();
|
||||
passengers.remove(e);
|
||||
});
|
||||
|
||||
if (speed == 0)
|
||||
return;
|
||||
|
@ -133,7 +166,16 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn
|
|||
return;
|
||||
}
|
||||
|
||||
if (((KineticTileEntity) te).getSpeed() == 0)
|
||||
if (entityIn instanceof ItemEntity) {
|
||||
if (speed == 0) {
|
||||
((ItemEntity) entityIn).setAgeToCreativeDespawnTime();
|
||||
} else {
|
||||
if (((ItemEntity) entityIn).getAge() > 0)
|
||||
((ItemEntity) entityIn).setNoDespawn();
|
||||
}
|
||||
}
|
||||
|
||||
if (speed == 0)
|
||||
return;
|
||||
|
||||
if (entityIn.posY - .25f < pos.getY())
|
||||
|
@ -143,6 +185,13 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn
|
|||
((LivingEntity) entityIn).setIdleTime(101);
|
||||
}
|
||||
|
||||
BeltTileEntity belt = (BeltTileEntity) te;
|
||||
|
||||
for (BeltAttachmentState state : belt.attachmentTracker.attachments) {
|
||||
if (state.attachment.handleEntity(belt, entityIn, state))
|
||||
return;
|
||||
}
|
||||
|
||||
final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING);
|
||||
final Slope slope = blockState.get(BeltBlock.SLOPE);
|
||||
final Axis axis = beltFacing.getAxis();
|
|
@ -1,4 +1,4 @@
|
|||
package com.simibubi.create.modules.contraptions.relays;
|
||||
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
package com.simibubi.create.modules.logistics.block;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.foundation.block.IWithTileEntity;
|
||||
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.AllBeltAttachments.IBeltAttachment;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.HorizontalBlock;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.item.BlockItemUseContext;
|
||||
import net.minecraft.state.StateContainer.Builder;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
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.util.math.shapes.VoxelShapes;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.IWorldReader;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, IWithTileEntity<BeltFunnelTileEntity> {
|
||||
|
||||
public static final VoxelShape SHAPE_NORTH = makeCuboidShape(4, 2, -1, 12, 10, 5),
|
||||
SHAPE_SOUTH = makeCuboidShape(4, 2, 11, 12, 10, 17), SHAPE_WEST = makeCuboidShape(-1, 2, 4, 5, 10, 12),
|
||||
SHAPE_EAST = makeCuboidShape(11, 2, 4, 17, 10, 12);
|
||||
|
||||
public BeltFunnelBlock() {
|
||||
super(Properties.from(Blocks.ANDESITE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTileEntity(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
|
||||
return new BeltFunnelTileEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillStateContainer(Builder<Block, BlockState> builder) {
|
||||
builder.add(HORIZONTAL_FACING);
|
||||
super.fillStateContainer(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
||||
BlockState state = getDefaultState();
|
||||
|
||||
if (context.getFace().getAxis().isHorizontal()) {
|
||||
state = state.with(HORIZONTAL_FACING, context.getFace().getOpposite());
|
||||
} else {
|
||||
state = state.with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing());
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
||||
Direction facing = state.get(HORIZONTAL_FACING);
|
||||
|
||||
if (facing == Direction.EAST)
|
||||
return SHAPE_EAST;
|
||||
if (facing == Direction.WEST)
|
||||
return SHAPE_WEST;
|
||||
if (facing == Direction.SOUTH)
|
||||
return SHAPE_SOUTH;
|
||||
if (facing == Direction.NORTH)
|
||||
return SHAPE_NORTH;
|
||||
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
|
||||
onAttachmentPlaced(worldIn, pos, state);
|
||||
updateObservedInventory(state, worldIn, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNeighborChange(BlockState state, IWorldReader world, BlockPos pos, BlockPos neighbor) {
|
||||
if (!neighbor.equals(pos.offset(state.get(HORIZONTAL_FACING))))
|
||||
return;
|
||||
updateObservedInventory(state, world, pos);
|
||||
}
|
||||
|
||||
private void updateObservedInventory(BlockState state, IWorldReader world, BlockPos pos) {
|
||||
IInventoryManipulator te = (IInventoryManipulator) world.getTileEntity(pos);
|
||||
if (te == null)
|
||||
return;
|
||||
te.neighborChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
onAttachmentRemoved(worldIn, pos, state);
|
||||
if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) {
|
||||
worldIn.removeTileEntity(pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BlockPos> getValidAttachmentFor(BeltTileEntity te) {
|
||||
BlockPos validPos = te.getPos().up();
|
||||
BlockState blockState = te.getWorld().getBlockState(validPos);
|
||||
if (blockState.getBlock() != this
|
||||
|| blockState.get(HORIZONTAL_FACING).getAxis() != te.getBlockState().get(HORIZONTAL_FACING).getAxis())
|
||||
return Optional.empty();
|
||||
return Optional.of(validPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) {
|
||||
BlockPos validPos = pos.down();
|
||||
BlockState blockState = world.getBlockState(validPos);
|
||||
if (!AllBlocks.BELT.typeOf(blockState)
|
||||
|| blockState.get(HORIZONTAL_FACING).getAxis() != state.get(HORIZONTAL_FACING).getAxis())
|
||||
return Optional.empty();
|
||||
return Optional.of(validPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
|
||||
if (!(entity instanceof ItemEntity))
|
||||
return false;
|
||||
if (entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos())) > .4f)
|
||||
return false;
|
||||
|
||||
entity.setMotion(Vec3d.ZERO);
|
||||
withTileEntityDo(te.getWorld(), state.attachmentPos, funnelTE -> {
|
||||
funnelTE.tryToInsert((ItemEntity) entity);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
package com.simibubi.create.modules.logistics.block;
|
||||
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.foundation.block.SyncedTileEntity;
|
||||
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.particles.ItemParticleData;
|
||||
import net.minecraft.particles.ParticleTypes;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.tileentity.ITickableTileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableTileEntity, IInventoryManipulator {
|
||||
|
||||
private LazyOptional<IItemHandler> inventory;
|
||||
protected boolean waitingForInventorySpace;
|
||||
private boolean initialize;
|
||||
|
||||
public BeltFunnelTileEntity() {
|
||||
super(AllTileEntities.BELT_FUNNEL.type);
|
||||
inventory = LazyOptional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
waitingForInventorySpace = compound.getBoolean("Waiting");
|
||||
super.read(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
initialize = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readClientUpdate(CompoundNBT tag) {
|
||||
super.readClientUpdate(tag);
|
||||
if (!waitingForInventorySpace)
|
||||
neighborChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
compound.putBoolean("Waiting", waitingForInventorySpace);
|
||||
return super.write(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getInventoryPos() {
|
||||
return pos.offset(getBlockState().get(BlockStateProperties.HORIZONTAL_FACING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LazyOptional<IItemHandler> getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (initialize && hasWorld()) {
|
||||
neighborChanged();
|
||||
initialize = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInventory(LazyOptional<IItemHandler> inventory) {
|
||||
this.inventory = inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void neighborChanged() {
|
||||
IInventoryManipulator.super.neighborChanged();
|
||||
waitingForInventorySpace = false;
|
||||
if (!world.isRemote)
|
||||
sendData();
|
||||
}
|
||||
|
||||
public void tryToInsert(ItemEntity entity) {
|
||||
if (!inventory.isPresent())
|
||||
return;
|
||||
if (waitingForInventorySpace)
|
||||
return;
|
||||
|
||||
ItemStack stack = entity.getItem().copy();
|
||||
IItemHandler inv = inventory.orElse(null);
|
||||
for (int slot = 0; slot < inv.getSlots(); slot++) {
|
||||
stack = inv.insertItem(slot, stack, world.isRemote);
|
||||
if (stack.isEmpty()) {
|
||||
if (!world.isRemote)
|
||||
entity.remove();
|
||||
else {
|
||||
Vec3i directionVec = getBlockState().get(BlockStateProperties.HORIZONTAL_FACING).getDirectionVec();
|
||||
float xSpeed = directionVec.getX() * 1/8f;
|
||||
float zSpeed = directionVec.getZ() * 1/8f;
|
||||
world.addParticle(new ItemParticleData(ParticleTypes.ITEM, entity.getItem()), entity.posX, entity.posY, entity.posZ, xSpeed, 1/6f, zSpeed);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
waitingForInventorySpace = true;
|
||||
sendData();
|
||||
|
||||
if (!stack.equals(entity.getItem(), false))
|
||||
entity.setItem(stack);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -14,10 +14,11 @@ public class ExtractorTileEntity extends SyncedTileEntity implements IExtractor,
|
|||
private State state;
|
||||
private int cooldown;
|
||||
private LazyOptional<IItemHandler> inventory;
|
||||
private boolean initialize;
|
||||
|
||||
public ExtractorTileEntity() {
|
||||
super(AllTileEntities.EXTRACTOR.type);
|
||||
state = State.WAITING_FOR_ITEM;
|
||||
state = State.WAITING_FOR_INVENTORY;
|
||||
inventory = LazyOptional.empty();
|
||||
}
|
||||
|
||||
|
@ -26,6 +27,20 @@ public class ExtractorTileEntity extends SyncedTileEntity implements IExtractor,
|
|||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
initialize = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (initialize && hasWorld()) {
|
||||
neighborChanged();
|
||||
initialize = false;
|
||||
}
|
||||
IExtractor.super.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(State state) {
|
||||
if (state == State.ON_COOLDOWN)
|
||||
|
|
|
@ -2,27 +2,22 @@ package com.simibubi.create.modules.logistics.block;
|
|||
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.ITickableTileEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
// Its like delegation but better!
|
||||
public interface IExtractor extends ITickableTileEntity {
|
||||
public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
|
||||
|
||||
public static final int EXTRACTOR_COOLDOWN = 20;
|
||||
public static final int EXTRACTION_COUNT = 16;
|
||||
|
||||
public enum State {
|
||||
WAITING_FOR_ITEM, WAITING_FOR_SPACE, RUNNING, ON_COOLDOWN, LOCKED;
|
||||
WAITING_FOR_INVENTORY, WAITING_FOR_ENTITY, RUNNING, ON_COOLDOWN, LOCKED;
|
||||
}
|
||||
|
||||
public State getState();
|
||||
|
@ -31,16 +26,6 @@ public interface IExtractor extends ITickableTileEntity {
|
|||
|
||||
public int tickCooldown();
|
||||
|
||||
public World getWorld();
|
||||
|
||||
public BlockPos getPos();
|
||||
|
||||
public BlockPos getInventoryPos();
|
||||
|
||||
public LazyOptional<IItemHandler> getInventory();
|
||||
|
||||
public void setInventory(LazyOptional<IItemHandler> inventory);
|
||||
|
||||
@Override
|
||||
default void tick() {
|
||||
State state = getState();
|
||||
|
@ -62,18 +47,18 @@ public interface IExtractor extends ITickableTileEntity {
|
|||
if (hasSpace && hasInventory)
|
||||
toExtract = extract(true);
|
||||
|
||||
if (state == State.WAITING_FOR_SPACE) {
|
||||
if (state == State.WAITING_FOR_ENTITY) {
|
||||
if (hasSpace)
|
||||
setState(State.RUNNING);
|
||||
}
|
||||
|
||||
if (state == State.RUNNING) {
|
||||
if (!hasSpace) {
|
||||
setState(State.WAITING_FOR_SPACE);
|
||||
setState(State.WAITING_FOR_ENTITY);
|
||||
return;
|
||||
}
|
||||
if (!hasInventory || toExtract.isEmpty()) {
|
||||
setState(State.WAITING_FOR_ITEM);
|
||||
setState(State.WAITING_FOR_INVENTORY);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -88,7 +73,7 @@ public interface IExtractor extends ITickableTileEntity {
|
|||
public default void setLocked(boolean locked) {
|
||||
setState(locked ? State.LOCKED : State.ON_COOLDOWN);
|
||||
}
|
||||
|
||||
|
||||
public default void neighborChanged() {
|
||||
boolean hasSpace = hasSpaceForExtracting();
|
||||
boolean hasInventory = getInventory().isPresent();
|
||||
|
@ -96,8 +81,8 @@ public interface IExtractor extends ITickableTileEntity {
|
|||
|
||||
if (hasSpace && hasInventory)
|
||||
toExtract = extract(true);
|
||||
|
||||
if (getState() == State.WAITING_FOR_ITEM) {
|
||||
|
||||
if (getState() == State.WAITING_FOR_INVENTORY) {
|
||||
if (!hasInventory) {
|
||||
if (findNewInventory()) {
|
||||
setState(State.RUNNING);
|
||||
|
@ -123,48 +108,27 @@ public interface IExtractor extends ITickableTileEntity {
|
|||
compare.setCount(extracting.getCount());
|
||||
if (!extracting.isEmpty() && !extracting.equals(compare, false))
|
||||
continue;
|
||||
|
||||
|
||||
if (extracting.isEmpty())
|
||||
extracting = stack.copy();
|
||||
else
|
||||
extracting.grow(stack.getCount());
|
||||
|
||||
|
||||
if (!simulate)
|
||||
inv.extractItem(slot, stack.getCount(), false);
|
||||
if (extracting.getCount() >= EXTRACTION_COUNT)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!simulate) {
|
||||
World world = getWorld();
|
||||
Vec3d pos = VecHelper.getCenterOf(getPos()).add(0, -0.5f, 0);
|
||||
ItemEntity entityIn = new ItemEntity(world, pos.x, pos.y, pos.z, extracting);
|
||||
entityIn.setMotion(Vec3d.ZERO);
|
||||
entityIn.setMotion(Vec3d.ZERO);
|
||||
world.addEntity(entityIn);
|
||||
}
|
||||
|
||||
return extracting;
|
||||
}
|
||||
|
||||
default boolean findNewInventory() {
|
||||
BlockPos invPos = getInventoryPos();
|
||||
World world = getWorld();
|
||||
|
||||
if (!world.isBlockPresent(invPos))
|
||||
return false;
|
||||
BlockState invState = world.getBlockState(invPos);
|
||||
|
||||
if (!invState.hasTileEntity())
|
||||
return false;
|
||||
TileEntity invTE = world.getTileEntity(invPos);
|
||||
|
||||
LazyOptional<IItemHandler> inventory = invTE.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
|
||||
setInventory(inventory);
|
||||
if (inventory.isPresent()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package com.simibubi.create.modules.logistics.block;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
public interface IInventoryManipulator {
|
||||
|
||||
public World getWorld();
|
||||
|
||||
public BlockPos getPos();
|
||||
|
||||
public BlockPos getInventoryPos();
|
||||
|
||||
public LazyOptional<IItemHandler> getInventory();
|
||||
|
||||
public void setInventory(LazyOptional<IItemHandler> inventory);
|
||||
|
||||
default boolean findNewInventory() {
|
||||
BlockPos invPos = getInventoryPos();
|
||||
World world = getWorld();
|
||||
|
||||
if (!world.isBlockPresent(invPos))
|
||||
return false;
|
||||
BlockState invState = world.getBlockState(invPos);
|
||||
|
||||
if (!invState.hasTileEntity())
|
||||
return false;
|
||||
TileEntity invTE = world.getTileEntity(invPos);
|
||||
|
||||
LazyOptional<IItemHandler> inventory = invTE.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
|
||||
setInventory(inventory);
|
||||
if (inventory.isPresent()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public default void neighborChanged() {
|
||||
boolean hasInventory = getInventory().isPresent();
|
||||
if (!hasInventory) {
|
||||
findNewInventory();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -22,7 +22,7 @@ public class LinkedExtractorTileEntity extends LinkedTileEntity
|
|||
|
||||
public LinkedExtractorTileEntity() {
|
||||
super(AllTileEntities.LINKED_EXTRACTOR.type);
|
||||
state = State.WAITING_FOR_ITEM;
|
||||
state = State.WAITING_FOR_INVENTORY;
|
||||
inventory = LazyOptional.empty();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package com.simibubi.create.modules.logistics.block;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.RedstoneDiodeBlock;
|
||||
import net.minecraft.state.BooleanProperty;
|
||||
import net.minecraft.state.StateContainer.Builder;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.TickPriority;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class PulseRepeaterBlock extends RedstoneDiodeBlock {
|
||||
|
||||
public static BooleanProperty PULSING = BooleanProperty.create("pulsing");
|
||||
|
||||
public PulseRepeaterBlock() {
|
||||
super(Properties.from(Blocks.REPEATER));
|
||||
setDefaultState(getDefaultState().with(PULSING, false).with(POWERED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDelay(BlockState state) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(BlockState state, World worldIn, BlockPos pos, Random random) {
|
||||
boolean powered = state.get(POWERED);
|
||||
boolean pulsing = state.get(PULSING);
|
||||
boolean shouldPower = shouldBePowered(worldIn, pos, state);
|
||||
|
||||
if (pulsing) {
|
||||
worldIn.setBlockState(pos, state.with(POWERED, true).with(PULSING, false), 2);
|
||||
} else if (powered && !shouldPower) {
|
||||
worldIn.setBlockState(pos, state.with(POWERED, false).with(PULSING, false), 2);
|
||||
} else if (!powered) {
|
||||
worldIn.setBlockState(pos, state.with(POWERED, true).with(PULSING, true), 2);
|
||||
worldIn.getPendingBlockTicks().scheduleTick(pos, this, this.getDelay(state), TickPriority.HIGH);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getActiveSignal(IBlockReader worldIn, BlockPos pos, BlockState state) {
|
||||
return state.get(PULSING) ? 15 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillStateContainer(Builder<Block, BlockState> builder) {
|
||||
builder.add(HORIZONTAL_FACING, POWERED, PULSING);
|
||||
super.fillStateContainer(builder);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"forge_marker": 1,
|
||||
"defaults": {
|
||||
"model": "create:block/belt_funnel"
|
||||
},
|
||||
"variants": {
|
||||
"facing": {
|
||||
"south": { "y": 180 },
|
||||
"east": { "y": 90 },
|
||||
"north": { "y": 0 },
|
||||
"west": { "y": 270 }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"variants": {
|
||||
"powered=false,pulsing=false,facing=south": { "model": "create:block/pulse_repeater" },
|
||||
"powered=false,pulsing=false,facing=north": { "model": "create:block/pulse_repeater", "y": 180 },
|
||||
"powered=false,pulsing=false,facing=east": { "model": "create:block/pulse_repeater", "y": 270 },
|
||||
"powered=false,pulsing=false,facing=west": { "model": "create:block/pulse_repeater", "y": 90 },
|
||||
|
||||
"powered=true,pulsing=false,facing=south": { "model": "create:block/pulse_repeater_powered" },
|
||||
"powered=true,pulsing=false,facing=north": { "model": "create:block/pulse_repeater_powered", "y": 180 },
|
||||
"powered=true,pulsing=false,facing=east": { "model": "create:block/pulse_repeater_powered", "y": 270 },
|
||||
"powered=true,pulsing=false,facing=west": { "model": "create:block/pulse_repeater_powered", "y": 90 },
|
||||
|
||||
"powered=false,pulsing=true,facing=south": { "model": "create:block/pulse_repeater_pulsing" },
|
||||
"powered=false,pulsing=true,facing=north": { "model": "create:block/pulse_repeater_pulsing", "y": 180 },
|
||||
"powered=false,pulsing=true,facing=east": { "model": "create:block/pulse_repeater_pulsing", "y": 270 },
|
||||
"powered=false,pulsing=true,facing=west": { "model": "create:block/pulse_repeater_pulsing", "y": 90 },
|
||||
|
||||
"powered=true,pulsing=true,facing=south": { "model": "create:block/pulse_repeater_pulsing" },
|
||||
"powered=true,pulsing=true,facing=north": { "model": "create:block/pulse_repeater_pulsing", "y": 180 },
|
||||
"powered=true,pulsing=true,facing=east": { "model": "create:block/pulse_repeater_pulsing", "y": 270 },
|
||||
"powered=true,pulsing=true,facing=west": { "model": "create:block/pulse_repeater_pulsing", "y": 90 }
|
||||
}
|
||||
}
|
|
@ -41,7 +41,9 @@
|
|||
"block.create.stockswitch": "Stockpile Switch",
|
||||
"block.create.flexcrate": "FlexCrate",
|
||||
"block.create.extractor": "Extractor",
|
||||
"block.create.belt_funnel": "Belt Funnel",
|
||||
"block.create.linked_extractor": "Linked Extractor",
|
||||
"block.create.pulse_repeater": "Pulse Repeater",
|
||||
|
||||
"block.create.andesite_bricks": "Andesite Bricks",
|
||||
"block.create.diorite_bricks": "Diorite Bricks",
|
||||
|
@ -74,6 +76,8 @@
|
|||
"block.create.shop_shelf": "Shelf",
|
||||
|
||||
"death.attack.create.crush": "%1$s was crushed by a dangerous contraption",
|
||||
"death.attack.create.fan_fire": "%1$s was burnt to death by hot air",
|
||||
"death.attack.create.fan_lava": "%1$s tried to swim up a lava fountain",
|
||||
|
||||
"itemGroup.create": "Create"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
{
|
||||
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"belt_funnel": "create:block/belt_funnel",
|
||||
"belt": "create:block/belt",
|
||||
"particle": "create:block/belt_funnel"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "Bottom",
|
||||
"from": [ 3, 0, -1 ],
|
||||
"to": [ 13, 1, 5 ],
|
||||
"faces": {
|
||||
"north": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] },
|
||||
"east": { "texture": "#belt_funnel", "uv": [ 9, 8, 10, 14 ], "rotation": 90 },
|
||||
"south": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] },
|
||||
"west": { "texture": "#belt_funnel", "uv": [ 0, 8, 1, 14 ], "rotation": 90 },
|
||||
"up": { "texture": "#belt_funnel", "uv": [ 0, 8, 10, 14 ] },
|
||||
"down": { "texture": "#belt_funnel", "uv": [ 0, 8, 10, 14 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Top",
|
||||
"from": [ 3, 7, -1 ],
|
||||
"to": [ 13, 8, 5 ],
|
||||
"faces": {
|
||||
"north": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] },
|
||||
"east": { "texture": "#belt_funnel", "uv": [ 9, 8, 10, 14 ], "rotation": 90 },
|
||||
"south": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] },
|
||||
"west": { "texture": "#belt_funnel", "uv": [ 0, 8, 1, 14 ], "rotation": 90 },
|
||||
"up": { "texture": "#belt_funnel", "uv": [ 0, 8, 10, 14 ] },
|
||||
"down": { "texture": "#belt_funnel", "uv": [ 0, 8, 10, 14 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Side",
|
||||
"from": [ 3, 1, -1 ],
|
||||
"to": [ 4, 7, 5 ],
|
||||
"faces": {
|
||||
"north": { "texture": "#belt_funnel", "uv": [ 9, 1, 10, 7 ] },
|
||||
"east": { "texture": "#belt_funnel", "uv": [ 9, 8, 10, 14 ], "rotation": 90 },
|
||||
"south": { "texture": "#belt_funnel", "uv": [ 0, 1, 1, 7 ] },
|
||||
"west": { "texture": "#belt_funnel", "uv": [ 0, 8, 1, 14 ], "rotation": 90 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Side",
|
||||
"from": [ 12, 1, -1 ],
|
||||
"to": [ 13, 7, 5 ],
|
||||
"faces": {
|
||||
"north": { "texture": "#belt_funnel", "uv": [ 0, 1, 1, 7 ] },
|
||||
"east": { "texture": "#belt_funnel", "uv": [ 9, 8, 10, 14 ], "rotation": 90 },
|
||||
"south": { "texture": "#belt_funnel", "uv": [ 9, 1, 10, 7 ] },
|
||||
"west": { "texture": "#belt_funnel", "uv": [ 0, 8, 1, 14 ], "rotation": 90 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Center",
|
||||
"from": [ 4, 1, -1 ],
|
||||
"to": [ 12, 7, 4 ],
|
||||
"faces": {
|
||||
"north": { "texture": "#belt_funnel", "uv": [ 1, 8, 9, 14 ] },
|
||||
"east": { "texture": "#belt_funnel", "uv": [ 9, 8, 10, 14 ], "rotation": 90 },
|
||||
"south": { "texture": "#belt_funnel", "uv": [ 1, 1, 9, 7 ] },
|
||||
"west": { "texture": "#belt_funnel", "uv": [ 0, 8, 1, 14 ], "rotation": 90 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Top",
|
||||
"from": [ 4, 6, 0 ],
|
||||
"to": [ 12, 8, 4.8 ],
|
||||
"rotation": { "origin": [ 8, 8, 0 ], "axis": "x", "angle": -22.5 },
|
||||
"faces": {
|
||||
"north": { "texture": "#belt_funnel", "uv": [ 1, 7, 9, 9 ], "rotation": 180 },
|
||||
"east": { "texture": "#belt_funnel", "uv": [ 0, 9.6, 1.8, 14 ], "rotation": 90 },
|
||||
"south": { "texture": "#belt_funnel", "uv": [ 1, 7, 9, 9 ] },
|
||||
"west": { "texture": "#belt_funnel", "uv": [ 0, 8, 2, 12.4 ], "rotation": 90 },
|
||||
"up": { "texture": "#belt_funnel", "uv": [ 1, 8, 9, 12.4 ], "rotation": 180 },
|
||||
"down": { "texture": "#belt_funnel", "uv": [ 1, 8, 9, 12.8 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Ramp",
|
||||
"from": [ 4, -0.9, 4 ],
|
||||
"to": [ 12, 1.1, 11 ],
|
||||
"rotation": { "origin": [ 8, 1, 5 ], "axis": "x", "angle": 45.0 },
|
||||
"faces": {
|
||||
"north": { "texture": "#belt", "uv": [ 0, 0, 8, 2 ] },
|
||||
"east": { "texture": "#belt", "uv": [ 14, 3, 16, 10 ], "rotation": 90 },
|
||||
"west": { "texture": "#belt", "uv": [ 0, 3, 2, 10 ], "rotation": 270 },
|
||||
"up": { "texture": "#belt", "uv": [ 4, 1, 12, 8 ] },
|
||||
"down": { "texture": "#belt", "uv": [ 0, 0, 8, 7 ] }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
101
src/main/resources/assets/create/models/item/belt_funnel.json
Normal file
101
src/main/resources/assets/create/models/item/belt_funnel.json
Normal file
|
@ -0,0 +1,101 @@
|
|||
{
|
||||
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
|
||||
"parent": "block/block",
|
||||
"display": {
|
||||
"gui": {
|
||||
"rotation": [ 30, 45, 0 ],
|
||||
"translation": [ 0, 0, 0],
|
||||
"scale":[ 0.625, 0.625, 0.625 ]
|
||||
}
|
||||
},
|
||||
"textures": {
|
||||
"belt_funnel": "create:block/belt_funnel",
|
||||
"symbols": "create:item/symbols"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "Indicator",
|
||||
"from": [ 8, 7, 13 ],
|
||||
"to": [ 16, 15, 13 ],
|
||||
"shade": false,
|
||||
"rotation": { "origin": [ 8, 8, 8 ], "axis": "y", "angle": -45.0 },
|
||||
"faces": {
|
||||
"north": { "texture": "#symbols", "uv": [ 0, 8, 8, 16 ] },
|
||||
"south": { "texture": "#symbols", "uv": [ 0, 8, 8, 16 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Bottom",
|
||||
"from": [ 3, 0, -1 ],
|
||||
"to": [ 13, 1, 5 ],
|
||||
"faces": {
|
||||
"north": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] },
|
||||
"east": { "texture": "#belt_funnel", "uv": [ 9, 8, 10, 14 ], "rotation": 90 },
|
||||
"south": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] },
|
||||
"west": { "texture": "#belt_funnel", "uv": [ 0, 8, 1, 14 ], "rotation": 90 },
|
||||
"up": { "texture": "#belt_funnel", "uv": [ 0, 8, 10, 14 ] },
|
||||
"down": { "texture": "#belt_funnel", "uv": [ 0, 8, 10, 14 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Top",
|
||||
"from": [ 3, 7, -1 ],
|
||||
"to": [ 13, 8, 5 ],
|
||||
"faces": {
|
||||
"north": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] },
|
||||
"east": { "texture": "#belt_funnel", "uv": [ 9, 8, 10, 14 ], "rotation": 90 },
|
||||
"south": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] },
|
||||
"west": { "texture": "#belt_funnel", "uv": [ 0, 8, 1, 14 ], "rotation": 90 },
|
||||
"up": { "texture": "#belt_funnel", "uv": [ 0, 8, 10, 14 ] },
|
||||
"down": { "texture": "#belt_funnel", "uv": [ 0, 8, 10, 14 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Side",
|
||||
"from": [ 3, 1, -1 ],
|
||||
"to": [ 4, 7, 5 ],
|
||||
"faces": {
|
||||
"north": { "texture": "#belt_funnel", "uv": [ 9, 1, 10, 7 ] },
|
||||
"east": { "texture": "#belt_funnel", "uv": [ 9, 8, 10, 14 ], "rotation": 90 },
|
||||
"south": { "texture": "#belt_funnel", "uv": [ 0, 1, 1, 7 ] },
|
||||
"west": { "texture": "#belt_funnel", "uv": [ 0, 8, 1, 14 ], "rotation": 90 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Side",
|
||||
"from": [ 12, 1, -1 ],
|
||||
"to": [ 13, 7, 5 ],
|
||||
"faces": {
|
||||
"north": { "texture": "#belt_funnel", "uv": [ 0, 1, 1, 7 ] },
|
||||
"east": { "texture": "#belt_funnel", "uv": [ 9, 8, 10, 14 ], "rotation": 90 },
|
||||
"south": { "texture": "#belt_funnel", "uv": [ 9, 1, 10, 7 ] },
|
||||
"west": { "texture": "#belt_funnel", "uv": [ 0, 8, 1, 14 ], "rotation": 90 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Center",
|
||||
"from": [ 4, 1, -1 ],
|
||||
"to": [ 12, 7, 4 ],
|
||||
"faces": {
|
||||
"north": { "texture": "#belt_funnel", "uv": [ 1, 8, 9, 14 ] },
|
||||
"east": { "texture": "#belt_funnel", "uv": [ 9, 8, 10, 14 ], "rotation": 90 },
|
||||
"south": { "texture": "#belt_funnel", "uv": [ 1, 1, 9, 7 ] },
|
||||
"west": { "texture": "#belt_funnel", "uv": [ 0, 8, 1, 14 ], "rotation": 90 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Top",
|
||||
"from": [ 4, 6, 0 ],
|
||||
"to": [ 12, 8, 4.8 ],
|
||||
"rotation": { "origin": [ 8, 8, 0 ], "axis": "x", "angle": -22.5 },
|
||||
"faces": {
|
||||
"north": { "texture": "#belt_funnel", "uv": [ 1, 7, 9, 9 ], "rotation": 180 },
|
||||
"east": { "texture": "#belt_funnel", "uv": [ 0, 9.6, 1.8, 14 ], "rotation": 90 },
|
||||
"south": { "texture": "#belt_funnel", "uv": [ 1, 7, 9, 9 ] },
|
||||
"west": { "texture": "#belt_funnel", "uv": [ 0, 8, 2, 12.4 ], "rotation": 90 },
|
||||
"up": { "texture": "#belt_funnel", "uv": [ 1, 8, 9, 12.4 ], "rotation": 180 },
|
||||
"down": { "texture": "#belt_funnel", "uv": [ 1, 8, 9, 12.8 ] }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,10 +1,129 @@
|
|||
{
|
||||
"parent": "create:block/extractor_wireless_powered",
|
||||
"parent": "block/block",
|
||||
"display": {
|
||||
"gui": {
|
||||
"rotation": [ 30, 45, 0 ],
|
||||
"translation": [ 0, 0, 0],
|
||||
"scale":[ 0.625, 0.625, 0.625 ]
|
||||
}
|
||||
}
|
||||
},
|
||||
"textures": {
|
||||
"redstone_antenna": "create:block/redstone_antenna",
|
||||
"extractor": "create:block/extractor",
|
||||
"symbols": "create:item/symbols"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "Indicator",
|
||||
"from": [ 8, 7, 13 ],
|
||||
"to": [ 16, 15, 13 ],
|
||||
"shade": false,
|
||||
"rotation": { "origin": [ 8, 8, 8 ], "axis": "y", "angle": -45.0 },
|
||||
"faces": {
|
||||
"north": { "texture": "#symbols", "uv": [ 0, 0, 8, 8 ] },
|
||||
"south": { "texture": "#symbols", "uv": [ 0, 0, 8, 8 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Bottom",
|
||||
"from": [ 4, 2, -1 ],
|
||||
"to": [ 12, 3, 5 ],
|
||||
"faces": {
|
||||
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
|
||||
"south": { "texture": "#extractor", "uv": [ 6, 7, 14, 8 ] },
|
||||
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
|
||||
"up": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 90 },
|
||||
"down": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 270 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Top",
|
||||
"from": [ 4, 9, -1 ],
|
||||
"to": [ 12, 10, 5 ],
|
||||
"faces": {
|
||||
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
|
||||
"south": { "texture": "#extractor", "uv": [ 6, 0, 14, 1 ] },
|
||||
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
|
||||
"up": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 90 },
|
||||
"down": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 270 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Side",
|
||||
"from": [ 4, 3, -1 ],
|
||||
"to": [ 5, 9, 5 ],
|
||||
"faces": {
|
||||
"east": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ], "rotation": 180 },
|
||||
"south": { "texture": "#extractor", "uv": [ 6, 1, 7, 7 ] },
|
||||
"west": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Side",
|
||||
"from": [ 11, 3, -1 ],
|
||||
"to": [ 12, 9, 5 ],
|
||||
"faces": {
|
||||
"east": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ], "rotation": 180 },
|
||||
"south": { "texture": "#extractor", "uv": [ 13, 1, 14, 7 ] },
|
||||
"west": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Center",
|
||||
"from": [ 5, 3, 3 ],
|
||||
"to": [ 11, 9, 4 ],
|
||||
"faces": {
|
||||
"south": { "texture": "#extractor", "uv": [ 7, 1, 13, 7 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "FilterSpot",
|
||||
"from": [ 5, 10, -0.6 ],
|
||||
"to": [ 11, 12, 4 ],
|
||||
"rotation": { "origin": [ 8, 11, -1 ], "axis": "x", "angle": 22.5 },
|
||||
"faces": {
|
||||
"north": { "texture": "#extractor", "uv": [ 13, 1, 15, 7 ], "rotation": 90 },
|
||||
"east": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ], "rotation": 180 },
|
||||
"south": { "texture": "#extractor", "uv": [ 4, 1, 5, 7 ], "rotation": 270 },
|
||||
"west": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ] },
|
||||
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "AntennaX",
|
||||
"from": [ 11, 7, 2 ],
|
||||
"to": [ 14, 17, 3 ],
|
||||
"faces": {
|
||||
"north": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] },
|
||||
"south": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] },
|
||||
"down": { "texture": "#redstone_antenna", "uv": [ 0, 9, 3, 10 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "AntennaZ",
|
||||
"from": [ 12, 7, 1 ],
|
||||
"to": [ 13, 17, 4 ],
|
||||
"faces": {
|
||||
"east": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] },
|
||||
"west": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "AntennaTop",
|
||||
"from": [ 12, 15, 2 ],
|
||||
"to": [ 13, 16, 3 ],
|
||||
"faces": {
|
||||
"up": { "texture": "#redstone_antenna", "uv": [ 1, 1, 2, 2 ] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "AntennaDish",
|
||||
"from": [ 10, 13, 0 ],
|
||||
"to": [ 15, 13, 5 ],
|
||||
"faces": {
|
||||
"up": { "texture": "#redstone_antenna", "uv": [ 4, 0, 9, 5 ] },
|
||||
"down": { "texture": "#redstone_antenna", "uv": [ 4, 0, 9, 5 ] }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "create:block/pulse_repeater"
|
||||
}
|
BIN
src/main/resources/assets/create/textures/block/belt_funnel.png
Normal file
BIN
src/main/resources/assets/create/textures/block/belt_funnel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 490 B |
BIN
src/main/resources/assets/create/textures/item/symbols.png
Normal file
BIN
src/main/resources/assets/create/textures/item/symbols.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 288 B |
Loading…
Reference in a new issue