SmartTileEntities and TileEntityBehaviour

- Added a TileEntity behaviour Interface
- Added SmartTileEntities, able to execute behaviours via delegation, replacing old Interface-based approaches
- Re-Implemented Filterable tiles/blocks as a TEBehaviour
- Re-Implemented Redstone-Linkable tiles/blocks as a TEBehaviour
- Added a base block for directional logistical attachments
- Belt Funnels are now Funnels
- Funnels can now face any direction
- Added Transposer blocks and Linked Transposer blocks (missing extraction behaviour)
- Unified in-world itemslot rendering used by filters and links
- Re-designed funnel, belt funnel and belt observer to match the extractor
- Started work on improved logistical casings
This commit is contained in:
simibubi 2020-01-05 19:41:38 +01:00
parent 039edb5519
commit 06ddb1fa35
103 changed files with 3858 additions and 2325 deletions

View file

@ -49,20 +49,20 @@ import com.simibubi.create.modules.curiosities.symmetry.block.CrossPlaneSymmetry
import com.simibubi.create.modules.curiosities.symmetry.block.PlaneSymmetryBlock;
import com.simibubi.create.modules.curiosities.symmetry.block.TriplePlaneSymmetryBlock;
import com.simibubi.create.modules.gardens.CocoaLogBlock;
import com.simibubi.create.modules.logistics.block.RedstoneBridgeBlock;
import com.simibubi.create.modules.logistics.block.RedstoneLinkBlock;
import com.simibubi.create.modules.logistics.block.StockswitchBlock;
import com.simibubi.create.modules.logistics.block.belts.BeltFunnelBlock;
import com.simibubi.create.modules.logistics.block.belts.EntityDetectorBlock;
import com.simibubi.create.modules.logistics.block.belts.ExtractorBlock;
import com.simibubi.create.modules.logistics.block.belts.LinkedExtractorBlock;
import com.simibubi.create.modules.logistics.block.belts.VerticalExtractorBlock;
import com.simibubi.create.modules.logistics.block.belts.VerticalLinkedExtractorBlock;
import com.simibubi.create.modules.logistics.block.belts.BeltObserverBlock;
import com.simibubi.create.modules.logistics.block.belts.FunnelBlock;
import com.simibubi.create.modules.logistics.block.diodes.FlexpeaterBlock;
import com.simibubi.create.modules.logistics.block.diodes.PulseRepeaterBlock;
import com.simibubi.create.modules.logistics.block.extractor.ExtractorBlock;
import com.simibubi.create.modules.logistics.block.extractor.LinkedExtractorBlock;
import com.simibubi.create.modules.logistics.block.inventories.FlexcrateBlock;
import com.simibubi.create.modules.logistics.management.base.LogisticalCasingBlock;
import com.simibubi.create.modules.logistics.block.transposer.LinkedTransposerBlock;
import com.simibubi.create.modules.logistics.block.transposer.TransposerBlock;
import com.simibubi.create.modules.logistics.management.base.LogisticalControllerBlock;
import com.simibubi.create.modules.logistics.management.base.LogisticalControllerBlock.LogisticalControllerIndicatorBlock;
import com.simibubi.create.modules.logistics.management.base.NewLogisticalCasingBlock;
import com.simibubi.create.modules.logistics.management.index.LogisticalIndexBlock;
import com.simibubi.create.modules.logistics.transport.villager.LogisticiansTableBlock;
import com.simibubi.create.modules.logistics.transport.villager.PackageFunnelBlock;
@ -160,21 +160,26 @@ public enum AllBlocks {
__LOGISTICS__(),
CONTACT(new ContactBlock()),
REDSTONE_BRIDGE(new RedstoneBridgeBlock()),
REDSTONE_BRIDGE(new RedstoneLinkBlock()),
STOCKSWITCH(new StockswitchBlock()),
FLEXCRATE(new FlexcrateBlock()),
EXTRACTOR(new ExtractorBlock()),
VERTICAL_EXTRACTOR(new VerticalExtractorBlock()),
VERTICAL_EXTRACTOR(new ExtractorBlock.Vertical()),
LINKED_EXTRACTOR(new LinkedExtractorBlock()),
VERTICAL_LINKED_EXTRACTOR(new VerticalLinkedExtractorBlock()),
BELT_FUNNEL(new BeltFunnelBlock()),
VERTICAL_LINKED_EXTRACTOR(new LinkedExtractorBlock.Vertical()),
TRANSPOSER(new TransposerBlock()),
VERTICAL_TRANSPOSER(new TransposerBlock.Vertical()),
LINKED_TRANSPOSER(new LinkedTransposerBlock()),
VERTICAL_LINKED_TRANSPOSER(new LinkedTransposerBlock.Vertical()),
BELT_FUNNEL(new FunnelBlock()),
VERTICAL_FUNNEL(new FunnelBlock.Vertical()),
BELT_TUNNEL(new BeltTunnelBlock()),
BELT_TUNNEL_FLAP(new RenderUtilityBlock()),
ENTITY_DETECTOR(new EntityDetectorBlock()),
ENTITY_DETECTOR(new BeltObserverBlock()),
PULSE_REPEATER(new PulseRepeaterBlock()),
FLEXPEATER(new FlexpeaterBlock()),
FLEXPEATER_INDICATOR(new RenderUtilityBlock()),
LOGISTICAL_CASING(new LogisticalCasingBlock()),
LOGISTICAL_CASING(new NewLogisticalCasingBlock()),
LOGISTICAL_CONTROLLER(new LogisticalControllerBlock()),
LOGISTICAL_CONTROLLER_INDICATOR(new LogisticalControllerIndicatorBlock()),
LOGISTICAL_INDEX(new LogisticalIndexBlock()),
@ -274,12 +279,13 @@ public enum AllBlocks {
public static void registerItemBlocks(IForgeRegistry<Item> registry) {
for (AllBlocks block : values()) {
if (block.get() == null)
Block def = block.get();
if (def == null)
continue;
if (block.get() instanceof IHaveNoBlockItem)
if (def instanceof IHaveNoBlockItem && !((IHaveNoBlockItem) def).hasBlockItem())
continue;
registerAsItem(registry, block.get());
registerAsItem(registry, def);
for (Block extra : block.alsoRegistered)
registerAsItem(registry, extra);
}
@ -301,6 +307,10 @@ public enum AllBlocks {
return block;
}
public BlockState getDefault() {
return block.getDefaultState();
}
public boolean typeOf(BlockState state) {
return state.getBlock() == block;
}

View file

@ -2,6 +2,7 @@ package com.simibubi.create;
import java.util.function.Supplier;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntityRenderer;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.actors.DrillTileEntity;
@ -48,20 +49,18 @@ import com.simibubi.create.modules.contraptions.relays.gearbox.GearboxTileEntity
import com.simibubi.create.modules.contraptions.relays.gearbox.GearboxTileEntityRenderer;
import com.simibubi.create.modules.contraptions.relays.gearbox.GearshiftTileEntity;
import com.simibubi.create.modules.curiosities.partialWindows.WindowInABlockTileEntity;
import com.simibubi.create.modules.logistics.block.LinkedTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.RedstoneBridgeTileEntity;
import com.simibubi.create.modules.logistics.block.RedstoneLinkTileEntity;
import com.simibubi.create.modules.logistics.block.StockswitchTileEntity;
import com.simibubi.create.modules.logistics.block.belts.BeltFunnelTileEntity;
import com.simibubi.create.modules.logistics.block.belts.BeltFunnelTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.belts.EntityDetectorTileEntity;
import com.simibubi.create.modules.logistics.block.belts.EntityDetectorTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.belts.ExtractorTileEntity;
import com.simibubi.create.modules.logistics.block.belts.ExtractorTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.belts.LinkedExtractorTileEntity;
import com.simibubi.create.modules.logistics.block.belts.LinkedExtractorTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.belts.BeltObserverTileEntity;
import com.simibubi.create.modules.logistics.block.belts.BeltObserverTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.belts.FunnelTileEntity;
import com.simibubi.create.modules.logistics.block.diodes.FlexpeaterTileEntity;
import com.simibubi.create.modules.logistics.block.diodes.FlexpeaterTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.extractor.ExtractorTileEntity;
import com.simibubi.create.modules.logistics.block.extractor.LinkedExtractorTileEntity;
import com.simibubi.create.modules.logistics.block.inventories.FlexcrateTileEntity;
import com.simibubi.create.modules.logistics.block.transposer.LinkedTransposerTileEntity;
import com.simibubi.create.modules.logistics.block.transposer.TransposerTileEntity;
import com.simibubi.create.modules.logistics.management.base.LogisticalCasingTileEntity;
import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntity;
import com.simibubi.create.modules.logistics.management.base.LogisticalControllerTileEntityRenderer;
@ -126,13 +125,18 @@ public enum AllTileEntities {
STRESS_GAUGE(StressGaugeTileEntity::new, AllBlocks.STRESS_GAUGE),
// Logistics
REDSTONE_BRIDGE(RedstoneBridgeTileEntity::new, AllBlocks.REDSTONE_BRIDGE),
REDSTONE_BRIDGE(RedstoneLinkTileEntity::new, AllBlocks.REDSTONE_BRIDGE),
STOCKSWITCH(StockswitchTileEntity::new, AllBlocks.STOCKSWITCH),
FLEXCRATE(FlexcrateTileEntity::new, AllBlocks.FLEXCRATE),
EXTRACTOR(ExtractorTileEntity::new, AllBlocks.EXTRACTOR, AllBlocks.VERTICAL_EXTRACTOR),
LINKED_EXTRACTOR(LinkedExtractorTileEntity::new, AllBlocks.LINKED_EXTRACTOR, AllBlocks.VERTICAL_LINKED_EXTRACTOR),
BELT_FUNNEL(BeltFunnelTileEntity::new, AllBlocks.BELT_FUNNEL),
ENTITY_DETECTOR(EntityDetectorTileEntity::new, AllBlocks.ENTITY_DETECTOR),
TRANSPOSER(TransposerTileEntity::new, AllBlocks.TRANSPOSER, AllBlocks.VERTICAL_TRANSPOSER),
LINKED_TRANSPOSER(
LinkedTransposerTileEntity::new,
AllBlocks.LINKED_TRANSPOSER,
AllBlocks.VERTICAL_LINKED_TRANSPOSER),
BELT_FUNNEL(FunnelTileEntity::new, AllBlocks.BELT_FUNNEL, AllBlocks.VERTICAL_FUNNEL),
ENTITY_DETECTOR(BeltObserverTileEntity::new, AllBlocks.ENTITY_DETECTOR),
FLEXPEATER(FlexpeaterTileEntity::new, AllBlocks.FLEXPEATER),
LOGISTICAL_CASING(LogisticalCasingTileEntity::new, AllBlocks.LOGISTICAL_CASING),
LOGISTICAL_SUPPLY_CONTROLLER(SupplyTileEntity::new, AllBlocks.LOGISTICAL_CONTROLLER),
@ -178,6 +182,7 @@ public enum AllTileEntities {
@OnlyIn(Dist.CLIENT)
public static void registerRenderers() {
bind(SchematicannonTileEntity.class, new SchematicannonRenderer());
bind(ShaftTileEntity.class, new KineticTileEntityRenderer());
bind(TurntableTileEntity.class, new KineticTileEntityRenderer());
bind(MotorTileEntity.class, new MotorTileEntityRenderer());
@ -189,26 +194,32 @@ public enum AllTileEntities {
bind(GearshiftTileEntity.class, new SplitShaftTileEntityRenderer());
bind(ClutchTileEntity.class, new SplitShaftTileEntityRenderer());
bind(BeltTileEntity.class, new BeltTileEntityRenderer());
bind(WaterWheelTileEntity.class, new KineticTileEntityRenderer());
bind(MechanicalPistonTileEntity.class, new MechanicalPistonTileEntityRenderer());
bind(MechanicalBearingTileEntity.class, new MechanicalBearingTileEntityRenderer());
bind(HarvesterTileEntity.class, new HarvesterTileEntityRenderer());
bind(CrushingWheelTileEntity.class, new KineticTileEntityRenderer());
bind(WaterWheelTileEntity.class, new KineticTileEntityRenderer());
bind(RedstoneBridgeTileEntity.class, new LinkedTileEntityRenderer());
bind(LinkedExtractorTileEntity.class, new LinkedExtractorTileEntityRenderer());
bind(ExtractorTileEntity.class, new ExtractorTileEntityRenderer());
bind(BeltFunnelTileEntity.class, new BeltFunnelTileEntityRenderer());
bind(BeltTunnelTileEntity.class, new BeltTunnelTileEntityRenderer());
bind(EntityDetectorTileEntity.class, new EntityDetectorTileEntityRenderer());
bind(MechanicalPressTileEntity.class, new MechanicalPressTileEntityRenderer());
bind(MechanicalMixerTileEntity.class, new MechanicalMixerTileEntityRenderer());
bind(MechanicalCrafterTileEntity.class, new MechanicalCrafterTileEntityRenderer());
bind(SpeedGaugeTileEntity.class, new GaugeTileEntityRenderer(GaugeBlock.Type.SPEED));
bind(StressGaugeTileEntity.class, new GaugeTileEntityRenderer(GaugeBlock.Type.STRESS));
bind(BasinTileEntity.class, new BasinTileEntityRenderer());
bind(RedstoneLinkTileEntity.class, new SmartTileEntityRenderer<>());
bind(ExtractorTileEntity.class, new SmartTileEntityRenderer<>());
bind(LinkedExtractorTileEntity.class, new SmartTileEntityRenderer<>());
bind(TransposerTileEntity.class, new SmartTileEntityRenderer<>());
bind(LinkedTransposerTileEntity.class, new SmartTileEntityRenderer<>());
bind(FunnelTileEntity.class, new SmartTileEntityRenderer<>());
bind(BeltTunnelTileEntity.class, new BeltTunnelTileEntityRenderer());
bind(BeltObserverTileEntity.class, new BeltObserverTileEntityRenderer());
bind(FlexpeaterTileEntity.class, new FlexpeaterTileEntityRenderer());
bind(LogisticalControllerTileEntity.class, new LogisticalControllerTileEntityRenderer());
bind(LogisticiansTableTileEntity.class, new LogisticiansTableTileEntityRenderer());
bind(HarvesterTileEntity.class, new HarvesterTileEntityRenderer());
bind(MechanicalMixerTileEntity.class, new MechanicalMixerTileEntityRenderer());
bind(MechanicalCrafterTileEntity.class, new MechanicalCrafterTileEntityRenderer());
bind(BasinTileEntity.class, new BasinTileEntityRenderer());
bind(SpeedGaugeTileEntity.class, new GaugeTileEntityRenderer(GaugeBlock.Type.SPEED));
bind(StressGaugeTileEntity.class, new GaugeTileEntityRenderer(GaugeBlock.Type.STRESS));
}
@OnlyIn(Dist.CLIENT)

View file

@ -10,7 +10,7 @@ import org.apache.logging.log4j.Logger;
import com.simibubi.create.foundation.world.OreGeneration;
import com.simibubi.create.modules.ModuleLoadedCondition;
import com.simibubi.create.modules.contraptions.TorquePropagator;
import com.simibubi.create.modules.logistics.FrequencyHandler;
import com.simibubi.create.modules.logistics.RedstoneLinkNetworkHandler;
import com.simibubi.create.modules.logistics.management.LogisticalNetworkHandler;
import com.simibubi.create.modules.logistics.transport.villager.LogisticianHandler;
import com.simibubi.create.modules.schematics.ServerSchematicLoader;
@ -44,7 +44,7 @@ public class Create {
public static Logger logger = LogManager.getLogger();
public static ItemGroup creativeTab = new CreateItemGroup();
public static ServerSchematicLoader schematicReceiver;
public static FrequencyHandler frequencyHandler;
public static RedstoneLinkNetworkHandler redstoneLinkNetworkHandler;
public static LogisticalNetworkHandler logisticalNetworkHandler;
public static TorquePropagator torquePropagator;
public static LogisticianHandler logisticianHandler;
@ -78,7 +78,7 @@ public class Create {
public static void init(final FMLCommonSetupEvent event) {
schematicReceiver = new ServerSchematicLoader();
frequencyHandler = new FrequencyHandler();
redstoneLinkNetworkHandler = new RedstoneLinkNetworkHandler();
logisticalNetworkHandler = new LogisticalNetworkHandler();
torquePropagator = new TorquePropagator();
lagger = new ServerLagger();

View file

@ -28,16 +28,17 @@ public final class CreateItemGroup extends ItemGroup {
public void addBlocks(NonNullList<ItemStack> items) {
for (AllBlocks block : AllBlocks.values()) {
if (block.get() == null)
Block def = block.get();
if (def == null)
continue;
if (!block.module.isEnabled())
continue;
if (block.get() instanceof IHaveNoBlockItem)
if (def instanceof IHaveNoBlockItem && !((IHaveNoBlockItem) def).hasBlockItem())
continue;
if (block.get() instanceof IAddedByOther)
if (def instanceof IAddedByOther)
continue;
block.get().asItem().fillItemGroup(this, items);
def.asItem().fillItemGroup(this, items);
for (Block alsoRegistered : block.alsoRegistered)
alsoRegistered.asItem().fillItemGroup(this, items);
}

View file

@ -43,7 +43,7 @@ public class Events {
@SubscribeEvent
public static void onLoadWorld(WorldEvent.Load event) {
IWorld world = event.getWorld();
Create.frequencyHandler.onLoadWorld(world);
Create.redstoneLinkNetworkHandler.onLoadWorld(world);
Create.logisticalNetworkHandler.onLoadWorld(world);
Create.torquePropagator.onLoadWorld(world);
}
@ -51,7 +51,7 @@ public class Events {
@SubscribeEvent
public static void onUnloadWorld(WorldEvent.Unload event) {
IWorld world = event.getWorld();
Create.frequencyHandler.onUnloadWorld(world);
Create.redstoneLinkNetworkHandler.onUnloadWorld(world);
Create.logisticalNetworkHandler.onUnloadWorld(world);
Create.torquePropagator.onUnloadWorld(world);
}

View file

@ -0,0 +1,21 @@
package com.simibubi.create.foundation.behaviour;
import com.simibubi.create.foundation.behaviour.base.IBehaviourType;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
public class LinkedBehaviour extends TileEntityBehaviour {
public static IBehaviourType<LinkedBehaviour> TYPE = new IBehaviourType<LinkedBehaviour>() {
};
public LinkedBehaviour(SmartTileEntity te) {
super(te);
}
@Override
public IBehaviourType<?> getType() {
return TYPE;
}
}

View file

@ -0,0 +1,40 @@
package com.simibubi.create.foundation.behaviour;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3d;
public class ValueBox {
String label = "Value Box";
Vec3d labelOffset = Vec3d.ZERO;
int passiveColor;
int highlightColor;
AxisAlignedBB bb = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
public ValueBox(String label, AxisAlignedBB bb) {
this.label = label;
this.bb = bb;
}
public ValueBox offsetLabel(Vec3d offset) {
this.labelOffset = offset;
return this;
}
public ValueBox withColors(int passive, int highlight) {
this.passiveColor = passive;
this.highlightColor = highlight;
return this;
}
public static class ItemValueBox extends ValueBox {
int count;
public ItemValueBox(String label, AxisAlignedBB bb, int count) {
super(label, bb);
this.count = count;
}
}
}

View file

@ -0,0 +1,82 @@
package com.simibubi.create.foundation.behaviour;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.behaviour.ValueBox.ItemValueBox;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3d;
@SuppressWarnings("deprecation")
public class ValueBoxRenderer {
public static void renderBox(ValueBox box, boolean highlighted) {
GlStateManager.enableBlend();
GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA,
GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE,
GlStateManager.DestFactor.ZERO);
GlStateManager.disableTexture();
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
bufferbuilder.begin(3, DefaultVertexFormats.POSITION_COLOR);
GlStateManager.lineWidth(highlighted ? 3 : 2);
Vec3d color = highlighted ? ColorHelper.getRGB(box.highlightColor) : ColorHelper.getRGB(box.passiveColor);
AxisAlignedBB bb = box.bb;
WorldRenderer.drawBoundingBox(bufferbuilder, bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ,
(float) color.x, (float) color.y, (float) color.z, 1f);
GlStateManager.lineWidth(2);
TessellatorHelper.draw();
GlStateManager.enableTexture();
float fontScale = -1 / 64f;
Vec3d shift = box.labelOffset;
GlStateManager.scaled(fontScale, fontScale, fontScale);
GlStateManager.translated(17.5f, -5f, 7f);
GlStateManager.translated(shift.x, shift.y, shift.z);
GlStateManager.rotated(0, 1, 0, 0);
FontRenderer font = Minecraft.getInstance().fontRenderer;
if (highlighted) {
String text = box.label;
font.drawString(text, 0, 0, box.highlightColor);
GlStateManager.translated(0, 0, -1 / 4f);
font.drawString(text, 1, 1, ColorHelper.mixColors(box.passiveColor, 0, 0.75f));
GlStateManager.translated(0, 0, 1 / 4f);
}
if (box instanceof ItemValueBox) {
String count = ((ItemValueBox) box).count + "";
GlStateManager.translated(-7 - font.getStringWidth(count), 10, 10 + 1 / 4f);
GlStateManager.scaled(1.5, 1.5, 1.5);
font.drawString(count, 0, 0, 0xEDEDED);
GlStateManager.translated(0, 0, -1 / 4f);
font.drawString(count, 1, 1, 0x4F4F4F);
}
}
public static void renderItemIntoValueBox(ItemStack filter) {
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
IBakedModel modelWithOverrides = itemRenderer.getModelWithOverrides(filter);
boolean blockItem = modelWithOverrides.isGui3d();
float scale = (!blockItem ? .5f : 1f) - 1 / 64f;
float zOffset = (!blockItem ? -.225f : 0);
GlStateManager.scaled(scale, scale, scale);
GlStateManager.translated(0, 0, zOffset);
itemRenderer.renderItem(filter, TransformType.FIXED);
}
}

View file

@ -0,0 +1,5 @@
package com.simibubi.create.foundation.behaviour.base;
public interface IBehaviourType<T extends TileEntityBehaviour> {
}

View file

@ -0,0 +1,111 @@
package com.simibubi.create.foundation.behaviour.base;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntityType;
public abstract class SmartTileEntity extends SyncedTileEntity implements ITickableTileEntity {
private Map<IBehaviourType<?>, TileEntityBehaviour> behaviours;
private boolean initialized;
private boolean firstNbtRead;
public SmartTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
behaviours = new HashMap<>();
initialized = false;
firstNbtRead = true;
ArrayList<TileEntityBehaviour> list = new ArrayList<>();
addBehaviours(list);
list.forEach(b -> behaviours.put(b.getType(), b));
}
public abstract void addBehaviours(List<TileEntityBehaviour> behaviours);
/**
* Gets called just before reading tile data for behaviours. Register anything
* here that depends on your custom te data.
*/
public void addBehavioursDeferred(List<TileEntityBehaviour> behaviours) {
}
@Override
public void tick() {
if (!initialized && hasWorld()) {
initialize();
initialized = true;
}
behaviours.values().forEach(TileEntityBehaviour::tick);
}
public void initialize() {
behaviours.values().forEach(TileEntityBehaviour::initialize);
}
public void updateClient(CompoundNBT compound) {
behaviours.values().forEach(tb -> tb.updateClient(compound));
}
@Override
public CompoundNBT write(CompoundNBT compound) {
behaviours.values().forEach(tb -> tb.writeNBT(compound));
return super.write(compound);
}
@Override
public void read(CompoundNBT compound) {
if (firstNbtRead) {
firstNbtRead = false;
ArrayList<TileEntityBehaviour> list = new ArrayList<>();
addBehavioursDeferred(list);
list.forEach(b -> behaviours.put(b.getType(), b));
}
forEachBehaviour(tb -> tb.readNBT(compound));
super.read(compound);
if (world != null && world.isRemote)
updateClient(compound);
}
@Override
public void remove() {
forEachBehaviour(TileEntityBehaviour::remove);
super.remove();
}
protected void forEachBehaviour(Consumer<TileEntityBehaviour> action) {
behaviours.values().forEach(tb -> {
if (!tb.isPaused())
action.accept(tb);
});
}
protected void putBehaviour(TileEntityBehaviour behaviour) {
behaviours.put(behaviour.getType(), behaviour);
behaviour.initialize();
}
protected void removeBehaviour(IBehaviourType<?> type) {
TileEntityBehaviour remove = behaviours.remove(type);
if (remove != null)
remove.remove();
}
@SuppressWarnings("unchecked")
protected <T extends TileEntityBehaviour> T getBehaviour(IBehaviourType<T> type) {
if (behaviours.containsKey(type))
return (T) behaviours.get(type);
return null;
}
}

View file

@ -0,0 +1,17 @@
package com.simibubi.create.foundation.behaviour.base;
import com.simibubi.create.foundation.behaviour.filtering.FilteringRenderer;
import com.simibubi.create.foundation.behaviour.linked.LinkRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
public class SmartTileEntityRenderer<T extends SmartTileEntity> extends TileEntityRenderer<T> {
@Override
public void render(T tileEntityIn, double x, double y, double z, float partialTicks, int destroyStage) {
super.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
FilteringRenderer.renderOnTileEntity(tileEntityIn, x, y, z, partialTicks, destroyStage);
LinkRenderer.renderOnTileEntity(tileEntityIn, x, y, z, partialTicks, destroyStage);
}
}

View file

@ -0,0 +1,85 @@
package com.simibubi.create.foundation.behaviour.base;
import net.minecraft.block.BlockState;
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.IEnviromentBlockReader;
import net.minecraft.world.World;
public abstract class TileEntityBehaviour {
public SmartTileEntity tileEntity;
private boolean paused;
public TileEntityBehaviour(SmartTileEntity te) {
tileEntity = te;
paused = false;
}
public abstract IBehaviourType<?> getType();
public void initialize() {
}
public void tick() {
}
public void readNBT(CompoundNBT nbt) {
}
public void updateClient(CompoundNBT nbt) {
}
public void writeNBT(CompoundNBT nbt) {
}
public void onBlockChanged(BlockState oldState) {
}
public void onNeighborChanged(Direction direction) {
}
public void remove() {
}
public boolean isPaused() {
return paused;
}
public void setPaused(boolean paused) {
this.paused = paused;
}
public BlockPos getPos() {
return tileEntity.getPos();
}
public World getWorld() {
return tileEntity.getWorld();
}
public static <T extends TileEntityBehaviour> T get(IEnviromentBlockReader reader, BlockPos pos,
IBehaviourType<T> type) {
return get(reader.getTileEntity(pos), type);
}
public static <T extends TileEntityBehaviour> T get(TileEntity te, IBehaviourType<T> type) {
if (te == null)
return null;
if (!(te instanceof SmartTileEntity))
return null;
SmartTileEntity ste = (SmartTileEntity) te;
return ste.getBehaviour(type);
}
}

View file

@ -0,0 +1,121 @@
package com.simibubi.create.foundation.behaviour.filtering;
import java.util.function.Consumer;
import java.util.function.Function;
import com.simibubi.create.foundation.behaviour.base.IBehaviourType;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.math.Vec3d;
public class FilteringBehaviour extends TileEntityBehaviour {
public static IBehaviourType<FilteringBehaviour> TYPE = new IBehaviourType<FilteringBehaviour>() {
};
SlotPositioning slotPositioning;
boolean showCount;
Vec3d textShift;
private ItemStack filter;
private Consumer<ItemStack> callback;
public FilteringBehaviour(SmartTileEntity te) {
super(te);
filter = ItemStack.EMPTY;
slotPositioning = new SlotPositioning(state -> Vec3d.ZERO, state -> Vec3d.ZERO);
showCount = false;
callback = stack -> {
};
textShift = Vec3d.ZERO;
}
@Override
public void writeNBT(CompoundNBT nbt) {
nbt.put("Filter", getFilter().serializeNBT());
super.writeNBT(nbt);
}
@Override
public void readNBT(CompoundNBT nbt) {
filter = ItemStack.read(nbt.getCompound("Filter"));
super.readNBT(nbt);
}
public FilteringBehaviour withCallback(Consumer<ItemStack> filterCallback) {
callback = filterCallback;
return this;
}
public FilteringBehaviour withSlotPositioning(SlotPositioning mapping) {
this.slotPositioning = mapping;
return this;
}
public FilteringBehaviour showCount() {
showCount = true;
return this;
}
public FilteringBehaviour moveText(Vec3d shift) {
textShift = shift;
return this;
}
public void setFilter(ItemStack stack) {
filter = stack.copy();
callback.accept(filter);
tileEntity.markDirty();
tileEntity.sendData();
}
public ItemStack getFilter() {
return filter.copy();
}
public boolean isCountVisible() {
return showCount && !getFilter().isEmpty();
}
public boolean test(ItemStack stack) {
return filter.isEmpty() || ItemStack.areItemsEqual(filter, stack);
}
@Override
public IBehaviourType<?> getType() {
return TYPE;
}
public boolean testHit(Vec3d hit) {
BlockState state = tileEntity.getBlockState();
Vec3d offset = slotPositioning.offset.apply(state);
if (offset == null)
return false;
Vec3d localHit = hit.subtract(new Vec3d(tileEntity.getPos()));
return localHit.distanceTo(offset) < slotPositioning.scale / 2;
}
public static class SlotPositioning {
Function<BlockState, Vec3d> offset;
Function<BlockState, Vec3d> rotation;
float scale;
public SlotPositioning(Function<BlockState, Vec3d> offsetForState,
Function<BlockState, Vec3d> rotationForState) {
offset = offsetForState;
rotation = rotationForState;
scale = 1;
}
public SlotPositioning scale(float scale) {
this.scale = scale;
return this;
}
}
}

View file

@ -0,0 +1,49 @@
package com.simibubi.create.foundation.behaviour.filtering;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.RaycastHelper;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class FilteringHandler {
@SubscribeEvent
public static void onBlockActivated(PlayerInteractEvent.RightClickBlock event) {
World world = event.getWorld();
BlockPos pos = event.getPos();
PlayerEntity player = event.getPlayer();
Hand hand = event.getHand();
if (player.isSneaking())
return;
FilteringBehaviour behaviour = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE);
if (behaviour == null)
return;
BlockRayTraceResult ray = RaycastHelper.rayTraceRange(world, player, 10);
if (ray == null)
return;
if (behaviour.testHit(ray.getHitVec())) {
if (event.getSide() != LogicalSide.CLIENT)
behaviour.setFilter(player.getHeldItem(hand));
event.setCanceled(true);
event.setCancellationResult(ActionResultType.SUCCESS);
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.BLOCKS, .25f, .1f);
}
}
}

View file

@ -0,0 +1,95 @@
package com.simibubi.create.foundation.behaviour.filtering;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.behaviour.ValueBox;
import com.simibubi.create.foundation.behaviour.ValueBox.ItemValueBox;
import com.simibubi.create.foundation.behaviour.ValueBoxRenderer;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.SlotPositioning;
import com.simibubi.create.foundation.utility.GlHelper;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT)
public class FilteringRenderer {
@SubscribeEvent
public static void renderBlockHighlight(DrawBlockHighlightEvent event) {
RayTraceResult target = event.getTarget();
if (target == null || !(target instanceof BlockRayTraceResult))
return;
BlockRayTraceResult result = (BlockRayTraceResult) target;
ClientWorld world = Minecraft.getInstance().world;
BlockPos pos = result.getPos();
BlockState state = world.getBlockState(pos);
FilteringBehaviour behaviour = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE);
if (behaviour == null)
return;
TessellatorHelper.prepareForDrawing();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
SlotPositioning slotPositioning = behaviour.slotPositioning;
renderTransformed(state, slotPositioning, () -> {
AxisAlignedBB bb = new AxisAlignedBB(Vec3d.ZERO, Vec3d.ZERO).grow(.25f);
String label = Lang.translate("logistics.filter");
ValueBox box = behaviour.isCountVisible() ? new ItemValueBox(label, bb, behaviour.getFilter().getCount())
: new ValueBox(label, bb);
box.offsetLabel(behaviour.textShift).withColors(0x7777BB, 0xCCBBFF);
ValueBoxRenderer.renderBox(box, behaviour.testHit(target.getHitVec()));
});
TessellatorHelper.cleanUpAfterDrawing();
}
public static void renderOnTileEntity(SmartTileEntity tileEntityIn, double x, double y, double z,
float partialTicks, int destroyStage) {
if (tileEntityIn == null || tileEntityIn.isRemoved())
return;
FilteringBehaviour behaviour = TileEntityBehaviour.get(tileEntityIn, FilteringBehaviour.TYPE);
if (behaviour == null)
return;
if (behaviour.getFilter().isEmpty())
return;
BlockState state = tileEntityIn.getBlockState();
SlotPositioning slotPositioning = behaviour.slotPositioning;
TessellatorHelper.prepareForDrawing();
BlockPos pos = tileEntityIn.getPos();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
renderTransformed(state, slotPositioning, () -> {
ValueBoxRenderer.renderItemIntoValueBox(behaviour.getFilter());
});
TessellatorHelper.cleanUpAfterDrawing();
}
private static void renderTransformed(BlockState state, SlotPositioning positioning, Runnable render) {
Vec3d position = positioning.offset.apply(state);
Vec3d rotation = positioning.rotation.apply(state);
float scale = positioning.scale;
GlHelper.renderTransformed(position, rotation, scale, render);
}
}

View file

@ -0,0 +1,188 @@
package com.simibubi.create.foundation.behaviour.linked;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.behaviour.base.IBehaviourType;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.modules.logistics.RedstoneLinkNetworkHandler;
import com.simibubi.create.modules.logistics.RedstoneLinkNetworkHandler.Frequency;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.math.Vec3d;
public class LinkBehaviour extends TileEntityBehaviour {
public static IBehaviourType<LinkBehaviour> TYPE = new IBehaviourType<LinkBehaviour>() {
};
enum Mode {
TRANSMIT, RECEIVE
}
Frequency frequencyFirst;
Frequency frequencyLast;
SlotPositioning slotPositioning;
Vec3d textShift;
private Mode mode;
private Supplier<Boolean> transmission;
private Consumer<Boolean> signalCallback;
protected LinkBehaviour(SmartTileEntity te) {
super(te);
slotPositioning = new SlotPositioning(state -> Pair.of(Vec3d.ZERO, Vec3d.ZERO), state -> Vec3d.ZERO);
frequencyFirst = new Frequency(ItemStack.EMPTY);
frequencyLast = new Frequency(ItemStack.EMPTY);
textShift = Vec3d.ZERO;
}
public static LinkBehaviour receiver(SmartTileEntity te, Consumer<Boolean> signalCallback) {
LinkBehaviour behaviour = new LinkBehaviour(te);
behaviour.signalCallback = signalCallback;
behaviour.mode = Mode.RECEIVE;
return behaviour;
}
public static LinkBehaviour transmitter(SmartTileEntity te, Supplier<Boolean> transmission) {
LinkBehaviour behaviour = new LinkBehaviour(te);
behaviour.transmission = transmission;
behaviour.mode = Mode.TRANSMIT;
return behaviour;
}
public LinkBehaviour withSlotPositioning(SlotPositioning mapping) {
this.slotPositioning = mapping;
return this;
}
public LinkBehaviour moveText(Vec3d shift) {
textShift = shift;
return this;
}
public void copyItemsFrom(LinkBehaviour behaviour) {
if (behaviour == null)
return;
frequencyFirst = behaviour.frequencyFirst;
frequencyLast = behaviour.frequencyLast;
}
public boolean isListening() {
return mode == Mode.RECEIVE;
}
public boolean isTransmitting() {
return mode == Mode.TRANSMIT && transmission.get();
}
public void updateReceiver(boolean networkPowered) {
signalCallback.accept(networkPowered);
}
public void notifySignalChange() {
Create.redstoneLinkNetworkHandler.updateNetworkOf(this);
}
@Override
public void initialize() {
super.initialize();
if (tileEntity.getWorld().isRemote)
return;
getHandler().addToNetwork(this);
}
public Pair<Frequency, Frequency> getNetworkKey() {
return Pair.of(frequencyFirst, frequencyLast);
}
@Override
public void remove() {
super.remove();
if (tileEntity.getWorld().isRemote)
return;
getHandler().removeFromNetwork(this);
}
@Override
public void writeNBT(CompoundNBT compound) {
super.writeNBT(compound);
compound.put("FrequencyFirst", frequencyFirst.getStack().write(new CompoundNBT()));
compound.put("FrequencyLast", frequencyLast.getStack().write(new CompoundNBT()));
}
@Override
public void readNBT(CompoundNBT compound) {
super.readNBT(compound);
frequencyFirst = new Frequency(ItemStack.read(compound.getCompound("FrequencyFirst")));
frequencyLast = new Frequency(ItemStack.read(compound.getCompound("FrequencyLast")));
}
public void setFrequency(boolean first, ItemStack stack) {
stack = stack.copy();
stack.setCount(1);
ItemStack toCompare = first ? frequencyFirst.getStack() : frequencyLast.getStack();
boolean changed = !ItemStack.areItemsEqual(stack, toCompare)
|| !ItemStack.areItemStackTagsEqual(stack, toCompare);
if (changed)
getHandler().removeFromNetwork(this);
if (first)
frequencyFirst = new Frequency(stack);
else
frequencyLast = new Frequency(stack);
if (!changed)
return;
tileEntity.sendData();
getHandler().addToNetwork(this);
}
@Override
public IBehaviourType<?> getType() {
return TYPE;
}
private RedstoneLinkNetworkHandler getHandler() {
return Create.redstoneLinkNetworkHandler;
}
public static class SlotPositioning {
Function<BlockState, Pair<Vec3d, Vec3d>> offsets;
Function<BlockState, Vec3d> rotation;
float scale;
public SlotPositioning(Function<BlockState, Pair<Vec3d, Vec3d>> offsetsForState,
Function<BlockState, Vec3d> rotationForState) {
offsets = offsetsForState;
rotation = rotationForState;
scale = 1;
}
public SlotPositioning scale(float scale) {
this.scale = scale;
return this;
}
}
public boolean testHit(Boolean first, Vec3d hit) {
BlockState state = tileEntity.getBlockState();
Pair<Vec3d, Vec3d> pair = slotPositioning.offsets.apply(state);
Vec3d offset = first ? pair.getKey() : pair.getValue();
if (offset == null)
return false;
Vec3d localHit = hit.subtract(new Vec3d(tileEntity.getPos()));
return localHit.distanceTo(offset) < slotPositioning.scale / 3.5f;
}
}

View file

@ -0,0 +1,53 @@
package com.simibubi.create.foundation.behaviour.linked;
import java.util.Arrays;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.RaycastHelper;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class LinkHandler {
@SubscribeEvent
public static void onBlockActivated(PlayerInteractEvent.RightClickBlock event) {
World world = event.getWorld();
BlockPos pos = event.getPos();
PlayerEntity player = event.getPlayer();
Hand hand = event.getHand();
if (player.isSneaking())
return;
LinkBehaviour behaviour = TileEntityBehaviour.get(world, pos, LinkBehaviour.TYPE);
if (behaviour == null)
return;
BlockRayTraceResult ray = RaycastHelper.rayTraceRange(world, player, 10);
if (ray == null)
return;
for (boolean first : Arrays.asList(false, true)) {
if (behaviour.testHit(first, ray.getHitVec())) {
if (event.getSide() != LogicalSide.CLIENT)
behaviour.setFrequency(first, player.getHeldItem(hand));
event.setCanceled(true);
event.setCancellationResult(ActionResultType.SUCCESS);
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.BLOCKS, .25f, .1f);
}
}
}
}

View file

@ -0,0 +1,98 @@
package com.simibubi.create.foundation.behaviour.linked;
import java.util.function.Consumer;
import org.apache.commons.lang3.tuple.Pair;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.behaviour.ValueBox;
import com.simibubi.create.foundation.behaviour.ValueBoxRenderer;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour.SlotPositioning;
import com.simibubi.create.foundation.utility.GlHelper;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT)
public class LinkRenderer {
@SubscribeEvent
public static void renderBlockHighlight(DrawBlockHighlightEvent event) {
RayTraceResult target = event.getTarget();
if (target == null || !(target instanceof BlockRayTraceResult))
return;
BlockRayTraceResult result = (BlockRayTraceResult) target;
ClientWorld world = Minecraft.getInstance().world;
BlockPos pos = result.getPos();
BlockState state = world.getBlockState(pos);
LinkBehaviour behaviour = TileEntityBehaviour.get(world, pos, LinkBehaviour.TYPE);
if (behaviour == null)
return;
TessellatorHelper.prepareForDrawing();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
SlotPositioning slotPositioning = behaviour.slotPositioning;
String freq1 = Lang.translate("logistics.firstFrequency");
String freq2 = Lang.translate("logistics.secondFrequency");
renderEachSlot(state, slotPositioning, first -> {
AxisAlignedBB bb = new AxisAlignedBB(Vec3d.ZERO, Vec3d.ZERO).grow(.25f);
String label = first ? freq2 : freq1;
ValueBox box = new ValueBox(label, bb).withColors(0x992266, 0xFF55AA).offsetLabel(behaviour.textShift);
ValueBoxRenderer.renderBox(box, behaviour.testHit(first, target.getHitVec()));
});
TessellatorHelper.cleanUpAfterDrawing();
}
public static void renderOnTileEntity(SmartTileEntity tileEntityIn, double x, double y, double z,
float partialTicks, int destroyStage) {
if (tileEntityIn == null || tileEntityIn.isRemoved())
return;
LinkBehaviour behaviour = TileEntityBehaviour.get(tileEntityIn, LinkBehaviour.TYPE);
if (behaviour == null)
return;
BlockState state = tileEntityIn.getBlockState();
SlotPositioning slotPositioning = behaviour.slotPositioning;
TessellatorHelper.prepareForDrawing();
BlockPos pos = tileEntityIn.getPos();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
renderEachSlot(state, slotPositioning, first -> {
ValueBoxRenderer.renderItemIntoValueBox(
first ? behaviour.frequencyFirst.getStack() : behaviour.frequencyLast.getStack());
});
TessellatorHelper.cleanUpAfterDrawing();
}
private static void renderEachSlot(BlockState state, SlotPositioning positioning, Consumer<Boolean> render) {
Pair<Vec3d, Vec3d> position = positioning.offsets.apply(state);
Vec3d rotation = positioning.rotation.apply(state);
float scale = positioning.scale;
GlHelper.renderTransformed(position.getKey(), rotation, scale, () -> render.accept(true));
GlHelper.renderTransformed(position.getValue(), rotation, scale, () -> render.accept(false));
}
}

View file

@ -5,4 +5,8 @@ package com.simibubi.create.foundation.block;
*/
public interface IHaveNoBlockItem {
default boolean hasBlockItem() {
return false;
}
}

View file

@ -1,7 +0,0 @@
package com.simibubi.create.foundation.block;
import net.minecraft.tileentity.TileEntity;
public abstract class TileEntityExtension<T extends TileEntity> {
}

View file

@ -23,9 +23,14 @@ public class AllShapes {
MOTOR_BLOCK = VoxelShaper.forHorizontal(makeCuboidShape(0, 3, 3, 16, 13, 13), Direction.EAST),
FOUR_VOXEL_POLE = VoxelShaper.forDirectionalAxis(makeCuboidShape(6, 0, 6, 10, 16, 10), Direction.Axis.Y),
SIX_VOXEL_POLE = VoxelShaper.forDirectionalAxis(makeCuboidShape(5, 0, 5, 11, 16, 11), Direction.Axis.Y),
FUNNEL = VoxelShaper.forDirectional(makeCuboidShape(3, -4, 11, 13, 8, 17), Direction.SOUTH),
BELT_FUNNEL = VoxelShaper.forHorizontal(makeCuboidShape(3, -4, 11, 13, 8, 17), Direction.SOUTH),
FUNNEL = VoxelShaper.forDirectional(makeCuboidShape(1, 1, 13, 15, 15, 17), Direction.SOUTH),
EXTRACTOR = VoxelShaper.forDirectional(makeCuboidShape(4, 2, 11, 12, 10, 17), Direction.SOUTH)
.withVerticalShapes(makeCuboidShape(4, 11, 4, 12, 17, 12))
.withVerticalShapes(makeCuboidShape(4, 11, 4, 12, 17, 12)),
TRANSPOSER = VoxelShaper.forDirectional(VoxelShapes.or(
makeCuboidShape(4, 4, -1, 12, 12, 1),
makeCuboidShape(5, 5, 0, 11, 11, 16),
makeCuboidShape(4, 4, 11, 12, 12, 17)), Direction.SOUTH)
;

View file

@ -0,0 +1,23 @@
package com.simibubi.create.foundation.utility;
import com.mojang.blaze3d.platform.GlStateManager;
import net.minecraft.util.math.Vec3d;
public class GlHelper {
public static void renderTransformed(Vec3d position, Vec3d rotation, float scale, Runnable render) {
if (position == null)
return;
GlStateManager.pushMatrix();
GlStateManager.translated(position.x, position.y, position.z);
GlStateManager.rotated(rotation.y, 0, 1, 0);
GlStateManager.rotated(rotation.z, 1, 0, 0);
GlStateManager.rotated(rotation.x, 0, 0, 1);
GlStateManager.scaled(scale, scale, scale);
render.run();
GlStateManager.popMatrix();
}
}

View file

@ -71,5 +71,9 @@ public class VecHelper {
public static Vec3d readNBT(ListNBT list) {
return new Vec3d(list.getDouble(0), list.getDouble(1), list.getDouble(2));
}
public static Vec3d voxelSpace(double x, double y, double z) {
return new Vec3d(x, y, z).scale(1 / 16f);
}
}

View file

@ -1,6 +1,7 @@
package com.simibubi.create.foundation.utility.recipe;
import com.google.common.base.Predicate;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
@ -30,8 +31,9 @@ public class RecipeConditions {
return r -> !r.getIngredients().isEmpty() && r.getIngredients().get(0).test(stack);
}
public static Predicate<IRecipe<?>> outputMatchesFilter(ItemStack filter) {
return r -> filter.isEmpty() || ItemStack.areItemsEqual(filter, r.getRecipeOutput());
public static Predicate<IRecipe<?>> outputMatchesFilter(FilteringBehaviour filtering) {
return r -> filtering.test(r.getRecipeOutput());
}
}

View file

@ -11,7 +11,8 @@ import java.util.UUID;
import com.simibubi.create.Create;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.KineticNetwork;
import com.simibubi.create.modules.contraptions.RotationPropagator;
@ -33,7 +34,7 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.ForgeConfigSpec.DoubleValue;
public abstract class KineticTileEntity extends SyncedTileEntity implements ITickableTileEntity {
public abstract class KineticTileEntity extends SmartTileEntity implements ITickableTileEntity {
int particleSpawnCountdown;
@ -59,6 +60,10 @@ public abstract class KineticTileEntity extends SyncedTileEntity implements ITic
source = Optional.empty();
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
}
public void sync(float maxStress, float currentStress) {
this.maxStress = maxStress;
this.currentStress = currentStress;

View file

@ -4,7 +4,6 @@ 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.logistics.block.IHaveFilterSlot;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -12,7 +11,6 @@ import net.minecraft.block.Blocks;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.InventoryHelper;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.BooleanProperty;
@ -22,19 +20,16 @@ import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
public class SawBlock extends DirectionalAxisKineticBlock
implements IWithTileEntity<SawTileEntity>, IHaveMovementBehavior, IHaveFilterSlot {
implements IWithTileEntity<SawTileEntity>, IHaveMovementBehavior {
public static final BooleanProperty RUNNING = BooleanProperty.create("running");
public static DamageSource damageSourceSaw = new DamageSource("create.saw").setDamageBypassesArmor();
@ -44,12 +39,6 @@ public class SawBlock extends DirectionalAxisKineticBlock
setDefaultState(getDefaultState().with(RUNNING, false));
}
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
return handleActivatedFilterSlots(state, worldIn, pos, player, handIn, hit);
}
@Override
public BlockRenderLayer getRenderLayer() {
return BlockRenderLayer.CUTOUT_MIPPED;
@ -146,26 +135,4 @@ public class SawBlock extends DirectionalAxisKineticBlock
}
@Override
public Vec3d getFilterPosition(BlockState state) {
Vec3d x = new Vec3d(8f / 16f, 12.5f / 16f + 1f / 256f, 12.25f / 16f);
Vec3d z = new Vec3d(12.25f / 16f, 12.5f / 16f + 1f / 256f, 8f / 16f);
return state.get(AXIS_ALONG_FIRST_COORDINATE) ? z : x;
}
@Override
public float getFilterAngle(BlockState state) {
return 0;
}
@Override
public boolean isFilterVisible(BlockState state) {
return state.get(FACING) == Direction.UP;
}
@Override
public Direction getFilterFacing(BlockState state) {
return state.get(AXIS_ALONG_FIRST_COORDINATE) ? Direction.EAST : Direction.SOUTH;
}
}

View file

@ -10,6 +10,9 @@ import java.util.stream.Collectors;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.SlotPositioning;
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.TreeCutter;
import com.simibubi.create.foundation.utility.TreeCutter.Tree;
@ -19,7 +22,6 @@ import com.simibubi.create.foundation.utility.recipe.RecipeFinder;
import com.simibubi.create.modules.contraptions.components.actors.BlockBreakingKineticTileEntity;
import com.simibubi.create.modules.contraptions.processing.ProcessingInventory;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.block.IHaveFilter;
import net.minecraft.block.BlockState;
import net.minecraft.entity.item.ItemEntity;
@ -45,23 +47,33 @@ import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
public class SawTileEntity extends BlockBreakingKineticTileEntity implements IHaveFilter {
public class SawTileEntity extends BlockBreakingKineticTileEntity {
private static final Object cuttingRecipesKey = new Object();
private static FilteringBehaviour.SlotPositioning slots;
public ProcessingInventory inventory;
private int recipeIndex;
private ItemStack filter;
private LazyOptional<IItemHandler> invProvider = LazyOptional.empty();
private FilteringBehaviour filtering;
public SawTileEntity() {
super(AllTileEntities.SAW.type);
inventory = new ProcessingInventory();
inventory.remainingTime = -1;
filter = ItemStack.EMPTY;
recipeIndex = 0;
invProvider = LazyOptional.of(() -> inventory);
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
super.addBehaviours(behaviours);
if (slots == null)
createSlotPositioning();
filtering = new FilteringBehaviour(this).withSlotPositioning(slots);
behaviours.add(filtering);
}
@Override
public boolean hasFastRenderer() {
return false;
@ -79,7 +91,6 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity implements IHa
@Override
public CompoundNBT write(CompoundNBT compound) {
inventory.write(compound);
compound.put("Filter", filter.write(new CompoundNBT()));
compound.putInt("RecipeIndex", recipeIndex);
return super.write(compound);
}
@ -89,7 +100,6 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity implements IHa
super.read(compound);
inventory = ProcessingInventory.read(compound);
recipeIndex = compound.getInt("RecipeIndex");
filter = ItemStack.read(compound.getCompound("Filter"));
}
@Override
@ -283,7 +293,7 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity implements IHa
private List<? extends IRecipe<?>> getRecipes() {
List<IRecipe<?>> startedSearch = RecipeFinder.get(cuttingRecipesKey, world,
RecipeConditions.isOfType(IRecipeType.STONECUTTING, AllRecipes.Types.CUTTING));
return startedSearch.stream().filter(RecipeConditions.outputMatchesFilter(filter))
return startedSearch.stream().filter(RecipeConditions.outputMatchesFilter(filtering))
.filter(RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0)))
.collect(Collectors.toList());
}
@ -342,18 +352,6 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity implements IHa
return getBlockState().get(SawBlock.FACING) == Direction.UP;
}
@Override
public void setFilter(ItemStack stack) {
filter = stack.copy();
markDirty();
sendData();
}
@Override
public ItemStack getFilter() {
return filter;
}
// Block Breaker
@Override
@ -391,4 +389,16 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity implements IHa
return super.canBreak(stateToBreak, blockHardness) && stateToBreak.isIn(BlockTags.LOGS);
}
protected void createSlotPositioning() {
slots = new SlotPositioning(state -> {
if (state.get(SawBlock.FACING) != Direction.UP)
return null;
Vec3d x = VecHelper.voxelSpace(8f, 12.5f, 12.25f);
Vec3d z = VecHelper.voxelSpace(12.25f, 12.5f, 8f);
return state.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? z : x;
}, state -> {
return new Vec3d(0, state.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 270 : 180, 90);
}).scale(.4f);
}
}

View file

@ -5,11 +5,11 @@ import static net.minecraft.state.properties.BlockStateProperties.FACING;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.behaviour.filtering.FilteringRenderer;
import com.simibubi.create.foundation.utility.TessellatorHelper;
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.logistics.block.FilteredTileEntityRenderer;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
@ -29,7 +29,7 @@ public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> {
@Override
public void render(SawTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) {
renderItems(te, x, y, z, partialTicks);
FilteredTileEntityRenderer.render(te, x, y, z, partialTicks, destroyStage);
FilteringRenderer.renderOnTileEntity(te, x, y, z, partialTicks, destroyStage);
renderShaft(te, x, y, z);
}

View file

@ -1,33 +0,0 @@
package com.simibubi.create.modules.logistics;
import com.simibubi.create.Create;
import com.simibubi.create.modules.logistics.FrequencyHandler.Frequency;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public interface IHaveWireless {
public Frequency getFrequencyFirst();
public Frequency getFrequencyLast();
public void setFrequency(boolean first, ItemStack stack);
public default World getWirelessWorld() {
return ((TileEntity) this).getWorld();
}
public default BlockPos getWirelessPos() {
return ((TileEntity) this).getPos();
}
public default boolean isLoaded() {
return getWirelessWorld().isBlockPresent(getWirelessPos());
}
default FrequencyHandler getHandler() {
return Create.frequencyHandler;
}
}

View file

@ -1,7 +0,0 @@
package com.simibubi.create.modules.logistics;
public interface IReceiveWireless extends IHaveWireless {
public void setSignal(boolean powered);
}

View file

@ -1,12 +0,0 @@
package com.simibubi.create.modules.logistics;
import com.simibubi.create.Create;
public interface ITransmitWireless extends IHaveWireless {
public boolean getSignal();
public default void notifySignalChange() {
Create.frequencyHandler.updateNetworkOf(this);
}
}

View file

@ -1,23 +1,25 @@
package com.simibubi.create.modules.logistics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.Create;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.world.IWorld;
public class FrequencyHandler {
public class RedstoneLinkNetworkHandler {
static Map<IWorld, Map<Pair<Frequency, Frequency>, List<IHaveWireless>>> connections = new HashMap<>();
static Map<IWorld, Map<Pair<Frequency, Frequency>, Set<LinkBehaviour>>> connections = new HashMap<>();
public static class Frequency {
private ItemStack stack;
@ -58,61 +60,65 @@ public class FrequencyHandler {
Create.logger.debug("Removed Redstone Network Space for " + world.getDimension().getType().getRegistryName());
}
private static Pair<Frequency, Frequency> getNetworkKey(IHaveWireless actor) {
return Pair.of(actor.getFrequencyFirst(), actor.getFrequencyLast());
}
public List<IHaveWireless> getNetworkOf(IHaveWireless actor) {
Map<Pair<Frequency, Frequency>, List<IHaveWireless>> networksInWorld = networksIn(actor.getWirelessWorld());
Pair<Frequency, Frequency> key = getNetworkKey(actor);
public Set<LinkBehaviour> getNetworkOf(LinkBehaviour actor) {
Map<Pair<Frequency, Frequency>, Set<LinkBehaviour>> networksInWorld = networksIn(actor.getWorld());
Pair<Frequency, Frequency> key = actor.getNetworkKey();
if (!networksInWorld.containsKey(key))
networksInWorld.put(key, new ArrayList<>());
networksInWorld.put(key, new HashSet<>());
return networksInWorld.get(key);
}
public void addToNetwork(IHaveWireless actor) {
public void addToNetwork(LinkBehaviour actor) {
getNetworkOf(actor).add(actor);
updateNetworkOf(actor);
}
public void removeFromNetwork(IHaveWireless actor) {
List<IHaveWireless> network = getNetworkOf(actor);
public void removeFromNetwork(LinkBehaviour actor) {
Set<LinkBehaviour> network = getNetworkOf(actor);
network.remove(actor);
if (network.isEmpty()) {
networksIn(actor.getWirelessWorld()).remove(getNetworkKey(actor));
networksIn(actor.getWorld()).remove(actor.getNetworkKey());
return;
}
updateNetworkOf(actor);
}
public void updateNetworkOf(IHaveWireless actor) {
List<IHaveWireless> network = getNetworkOf(actor);
public void updateNetworkOf(LinkBehaviour actor) {
Set<LinkBehaviour> network = getNetworkOf(actor);
boolean powered = false;
// Update from Transmitters
for (IHaveWireless other : network) {
if (!other.isLoaded() || !withinRange(actor, other))
for (Iterator<LinkBehaviour> iterator = network.iterator(); iterator.hasNext();) {
LinkBehaviour other = iterator.next();
if (other.tileEntity.isRemoved()) {
iterator.remove();
continue;
if (other instanceof ITransmitWireless && ((ITransmitWireless) other).getSignal()) {
}
if (!withinRange(actor, other))
continue;
if (other.isTransmitting()) {
powered = true;
break;
}
}
// Update the Receivers
for (IHaveWireless other : network) {
if (!other.isLoaded() || !withinRange(actor, other))
for (Iterator<LinkBehaviour> iterator = network.iterator(); iterator.hasNext();) {
LinkBehaviour other = iterator.next();
if (other.tileEntity.isRemoved()) {
iterator.remove();
continue;
if (other instanceof IReceiveWireless)
((IReceiveWireless) other).setSignal(powered);
}
if (!withinRange(actor, other))
continue;
if (other.isListening())
other.updateReceiver(powered);
}
}
public static boolean withinRange(IHaveWireless from, IHaveWireless to) {
return from.getWirelessPos().withinDistance(to.getWirelessPos(), CreateConfig.parameters.linkRange.get());
public static boolean withinRange(LinkBehaviour from, LinkBehaviour to) {
return from.getPos().withinDistance(to.getPos(), CreateConfig.parameters.linkRange.get());
}
public Map<Pair<Frequency, Frequency>, List<IHaveWireless>> networksIn(IWorld world) {
public Map<Pair<Frequency, Frequency>, Set<LinkBehaviour>> networksIn(IWorld world) {
if (!connections.containsKey(world)) {
Create.logger.warn(
"Tried to Access unprepared network space of " + world.getDimension().getType().getRegistryName());

View file

@ -1,79 +0,0 @@
package com.simibubi.create.modules.logistics.block;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
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;
@SuppressWarnings("deprecation")
public class FilteredTileEntityRenderer {
public static <T extends TileEntity & IHaveFilter> void render(T tileEntityIn, double x, double y, double z,
float partialTicks, int destroyStage) {
BlockState state = tileEntityIn.getBlockState();
IHaveFilterSlot block = (IHaveFilterSlot) state.getBlock();
if (!block.isFilterVisible(state))
return;
Direction facing = block.getFilterFacing(state);
float scale = block.getItemHitboxScale();
TessellatorHelper.prepareForDrawing();
Vec3d position = block.getFilterPosition(state);
BlockPos pos = tileEntityIn.getPos();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
renderFilterItem(tileEntityIn.getFilter(), position, facing, scale - 2 / 16f, block.getFilterAngle(state));
TessellatorHelper.cleanUpAfterDrawing();
}
private static void renderFilterItem(ItemStack stack, Vec3d position, Direction facing, float scaleDiff,
float angle) {
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
boolean vertical = facing.getAxis().isVertical();
IBakedModel modelWithOverrides = itemRenderer.getModelWithOverrides(stack);
boolean blockItem = modelWithOverrides.isGui3d();
float offX = 0;
float offY = 0;
float offZ = !blockItem ? 1 / 4f + 2 * scaleDiff - 1 / 16f : 1 / 16f;
if (vertical)
offZ = -offZ;
float rotX = vertical ? 90 : 0 - (blockItem ? -90f + angle : 90 - angle);
float rotY = vertical ? 0 : facing.getHorizontalAngle() + (blockItem ? 180 : 0);
float rotZ = vertical && facing == Direction.DOWN ? 180 : 0;
if (facing.getAxis() == Axis.X) {
rotY = -rotY;
}
float scale = !blockItem ? .25f : .5f;
scale *= 1 + 8 * scaleDiff;
GlStateManager.pushMatrix();
GlStateManager.translated(position.x, position.y, position.z);
GlStateManager.rotatef(rotZ, 0, 0, 1);
GlStateManager.rotatef(rotY, 0, 1, 0);
GlStateManager.rotatef(rotX, 1, 0, 0);
GlStateManager.scaled(scale, scale, scale);
GlStateManager.translatef(offX, offY, offZ);
itemRenderer.renderItem(stack, TransformType.FIXED);
GlStateManager.popMatrix();
}
}

View file

@ -1,176 +0,0 @@
package com.simibubi.create.modules.logistics.block;
import org.apache.commons.lang3.tuple.Pair;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.modules.logistics.IHaveWireless;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.player.PlayerEntity;
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.Hand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
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.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT)
public interface IBlockWithFrequency {
public Pair<Vec3d, Vec3d> getFrequencyItemPositions(BlockState state);
public Direction getFrequencyItemFacing(BlockState state);
public default float getItemHitboxScale() {
return 2 / 16f;
}
public default boolean handleActivatedFrequencySlots(BlockState state, World worldIn, BlockPos pos, PlayerEntity player,
Hand handIn, BlockRayTraceResult hit) {
TileEntity te = worldIn.getTileEntity(pos);
if (te == null || !(te instanceof IHaveWireless))
return false;
IHaveWireless actor = (IHaveWireless) te;
Pair<Vec3d, Vec3d> positions = getFrequencyItemPositions(state);
ItemStack stack = player.getHeldItem(handIn);
Vec3d vec = new Vec3d(pos);
Vec3d first = positions.getLeft().add(vec);
Vec3d second = positions.getRight().add(vec);
float scale = getItemHitboxScale();
if (new AxisAlignedBB(first, first).grow(scale).contains(hit.getHitVec())) {
if (worldIn.isRemote)
return true;
actor.setFrequency(true, stack);
return true;
}
if (new AxisAlignedBB(second, second).grow(scale).contains(hit.getHitVec())) {
if (worldIn.isRemote)
return true;
actor.setFrequency(false, stack);
return true;
}
return false;
}
@SubscribeEvent
@OnlyIn(Dist.CLIENT)
public static void onDrawBlockHighlight(DrawBlockHighlightEvent event) {
if (event.getTarget() == null || !(event.getTarget() instanceof BlockRayTraceResult))
return;
BlockRayTraceResult result = (BlockRayTraceResult) event.getTarget();
ClientWorld world = Minecraft.getInstance().world;
BlockPos pos = result.getPos();
BlockState state = world.getBlockState(pos);
if (!(state.getBlock() instanceof IBlockWithFrequency))
return;
IBlockWithFrequency freqBlock = (IBlockWithFrequency) state.getBlock();
Pair<Vec3d, Vec3d> positions = freqBlock.getFrequencyItemPositions(state);
Vec3d vec = new Vec3d(pos);
Vec3d first = positions.getLeft().add(vec);
Vec3d second = positions.getRight().add(vec);
float scale = freqBlock.getItemHitboxScale();
Direction facing = freqBlock.getFrequencyItemFacing(state);
AxisAlignedBB firstBB = new AxisAlignedBB(first, first).grow(scale);
AxisAlignedBB secondBB = new AxisAlignedBB(second, second).grow(scale);
TessellatorHelper.prepareForDrawing();
GlStateManager.enableBlend();
GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA,
GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE,
GlStateManager.DestFactor.ZERO);
GlStateManager.disableTexture();
GlStateManager.depthMask(false);
GlStateManager.matrixMode(5889);
boolean firstContains = firstBB.contains(result.getHitVec());
if (firstContains) {
GlStateManager.lineWidth(2);
WorldRenderer.drawSelectionBoundingBox(firstBB.grow(1 / 128f), 1, 1, .5f, 1f);
} else {
GlStateManager.lineWidth(2);
WorldRenderer.drawSelectionBoundingBox(firstBB.grow(1 / 128f), .5f, .5f, .2f, 1f);
}
boolean secondContains = secondBB.contains(result.getHitVec());
if (secondContains) {
GlStateManager.lineWidth(2);
WorldRenderer.drawSelectionBoundingBox(secondBB.grow(1 / 128f), 1, 1, .5f, 1f);
} else {
GlStateManager.lineWidth(2);
WorldRenderer.drawSelectionBoundingBox(secondBB.grow(1 / 128f), .5f, .5f, .2f, 1f);
}
GlStateManager.matrixMode(5888);
GlStateManager.depthMask(true);
GlStateManager.enableTexture();
if (firstContains) {
GlStateManager.pushMatrix();
float textScale = 1 / 128f;
GlStateManager.translated(first.x, first.y, first.z);
if (facing.getAxis().isVertical()) {
GlStateManager.rotated(180, 0, 1, 0);
GlStateManager.rotated(facing == Direction.UP ? -90 : 90, 1, 0, 0);
} else {
GlStateManager.rotated(facing.getHorizontalAngle() * (facing.getAxis() == Axis.X ? -1 : 1), 0, 1, 0);
}
GlStateManager.scaled(textScale, -textScale, textScale);
GlStateManager.translated(19.5f, -5f, 10f);
String text = Lang.translate("logistics.secondFrequency");
Minecraft.getInstance().fontRenderer.drawString(text, 0, 0, 0xFFFF99);
GlStateManager.translated(0, 0, -1 / 4f);
Minecraft.getInstance().fontRenderer.drawString(text, 1, 1, 0x444433);
GlStateManager.popMatrix();
}
if (secondContains) {
GlStateManager.pushMatrix();
float textScale = 1 / 128f;
GlStateManager.translated(second.x, second.y, second.z);
if (facing.getAxis().isVertical()) {
GlStateManager.rotated(180, 0, 1, 0);
GlStateManager.rotated(facing == Direction.UP ? -90 : 90, 1, 0, 0);
} else {
GlStateManager.rotated(facing.getHorizontalAngle() * (facing.getAxis() == Axis.X ? -1 : 1), 0, 1, 0);
}
GlStateManager.scaled(textScale, -textScale, textScale);
GlStateManager.translated(19.5f, -5f, 10f);
String text = Lang.translate("logistics.firstFrequency");
Minecraft.getInstance().fontRenderer.drawString(text, 0, 0, 0xFFFF99);
GlStateManager.translated(0, 0, -1 / 4f);
Minecraft.getInstance().fontRenderer.drawString(text, 1, 1, 0x444433);
GlStateManager.popMatrix();
}
GlStateManager.disableBlend();
GlStateManager.disableBlend();
GlStateManager.lineWidth(1);
TessellatorHelper.cleanUpAfterDrawing();
}
}

View file

@ -4,6 +4,8 @@ import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FAC
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.item.CardboardBoxItem;
@ -63,8 +65,7 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
if (hasSpace && hasInventory) {
toExtract = extract(true);
ItemStack filterItem = (this instanceof IHaveFilter) ? ((IHaveFilter) this).getFilter() : ItemStack.EMPTY;
if (!filterItem.isEmpty() && !ItemStack.areItemsEqual(toExtract, filterItem))
if (!matchesFilter(toExtract))
toExtract = ItemStack.EMPTY;
}
@ -85,12 +86,16 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
extract(false);
setState(State.ON_COOLDOWN);
return;
}
}
default boolean matchesFilter(ItemStack stack) {
FilteringBehaviour filteringBehaviour = TileEntityBehaviour.get((TileEntity) this, FilteringBehaviour.TYPE);
return filteringBehaviour == null || filteringBehaviour.test(stack);
}
public default void setLocked(boolean locked) {
setState(locked ? State.LOCKED : State.ON_COOLDOWN);
}
@ -105,8 +110,7 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
if (hasSpace && hasInventory) {
toExtract = extract(true);
ItemStack filterItem = (this instanceof IHaveFilter) ? ((IHaveFilter) this).getFilter() : ItemStack.EMPTY;
if (!filterItem.isEmpty() && !ItemStack.areItemsEqual(toExtract, filterItem))
if (!matchesFilter(toExtract))
toExtract = ItemStack.EMPTY;
}
@ -144,7 +148,8 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
default ItemStack extract(boolean simulate) {
IItemHandler inv = getInventory().orElse(null);
ItemStack extracting = ItemStack.EMPTY;
ItemStack filterItem = (this instanceof IHaveFilter) ? ((IHaveFilter) this).getFilter() : ItemStack.EMPTY;
FilteringBehaviour filteringBehaviour = TileEntityBehaviour.get((TileEntity) this, FilteringBehaviour.TYPE);
ItemStack filterItem = filteringBehaviour == null ? ItemStack.EMPTY : filteringBehaviour.getFilter();
World world = getWorld();
int extractionCount = filterItem.isEmpty() ? CreateConfig.parameters.extractorAmount.get()
: filterItem.getCount();

View file

@ -1,10 +0,0 @@
package com.simibubi.create.modules.logistics.block;
import net.minecraft.item.ItemStack;
public interface IHaveFilter {
public void setFilter(ItemStack stack);
public ItemStack getFilter();
}

View file

@ -1,180 +0,0 @@
package com.simibubi.create.modules.logistics.block;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.player.PlayerEntity;
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.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT)
public interface IHaveFilterSlot {
public Vec3d getFilterPosition(BlockState state);
public Direction getFilterFacing(BlockState state);
public default float getItemHitboxScale() {
return 2 / 16f;
}
public default float getFilterAngle(BlockState state) {
return 22.5f;
}
public default boolean isFilterVisible(BlockState state) {
return true;
}
public default boolean showsCount() {
return false;
}
public default boolean handleActivatedFilterSlots(BlockState state, World worldIn, BlockPos pos,
PlayerEntity player, Hand handIn, BlockRayTraceResult hit) {
TileEntity te = worldIn.getTileEntity(pos);
if (te == null || !(te instanceof IHaveFilter))
return false;
if (!isFilterVisible(state))
return false;
IHaveFilter actor = (IHaveFilter) te;
Vec3d vec = new Vec3d(pos);
Vec3d position = vec.add(getFilterPosition(state));
ItemStack stack = player.getHeldItem(handIn);
float scale = getItemHitboxScale();
if (new AxisAlignedBB(position, position).grow(scale * 2).contains(hit.getHitVec())) {
if (worldIn.isRemote)
return true;
actor.setFilter(stack);
return true;
}
return false;
}
@SubscribeEvent
@OnlyIn(Dist.CLIENT)
public static void onDrawBlockHighlight(DrawBlockHighlightEvent event) {
if (event.getTarget() == null || !(event.getTarget() instanceof BlockRayTraceResult))
return;
BlockRayTraceResult result = (BlockRayTraceResult) event.getTarget();
ClientWorld world = Minecraft.getInstance().world;
BlockPos pos = result.getPos();
BlockState state = world.getBlockState(pos);
if (!(state.getBlock() instanceof IHaveFilterSlot))
return;
TileEntity te = world.getTileEntity(pos);
if (te == null || !(te instanceof IHaveFilter))
return;
IHaveFilter actor = (IHaveFilter) te;
IHaveFilterSlot filterBlock = (IHaveFilterSlot) state.getBlock();
if (!filterBlock.isFilterVisible(state))
return;
Vec3d vec = new Vec3d(pos);
Vec3d position = filterBlock.getFilterPosition(state).add(vec);
float scale = filterBlock.getItemHitboxScale();
AxisAlignedBB bb = new AxisAlignedBB(position, position).grow(scale, scale / 1.25f, scale).offset(0,
-scale / 16f, 0);
boolean contains = bb.grow(scale).contains(result.getHitVec());
TessellatorHelper.prepareForDrawing();
GlStateManager.enableBlend();
GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA,
GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE,
GlStateManager.DestFactor.ZERO);
GlStateManager.disableTexture();
GlStateManager.depthMask(false);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
bufferbuilder.begin(3, DefaultVertexFormats.POSITION_COLOR);
bb = bb.grow(1 / 128f);
Vec3d center = bb.getCenter().subtract(vec);
bb = bb.offset(center);
Direction facing = filterBlock.getFilterFacing(state);
Vec3i direction = facing.getDirectionVec();
GlStateManager.pushMatrix();
GlStateManager.translated(position.x, position.y, position.z);
float filterAngle = filterBlock.getFilterAngle(state);
GlStateManager.rotated(filterAngle, direction.getZ(), 0, -direction.getX());
GlStateManager.translated(-center.x, -center.y, -center.z);
GlStateManager.translated(-position.x, -position.y, -position.z);
if (contains) {
GlStateManager.lineWidth(2);
WorldRenderer.drawBoundingBox(bufferbuilder, bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ, .5f, 1,
.75f, 1f);
} else {
GlStateManager.lineWidth(2);
WorldRenderer.drawBoundingBox(bufferbuilder, bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ, .25f,
.5f, .35f, 1f);
}
tessellator.draw();
GlStateManager.enableTexture();
GlStateManager.depthMask(true);
if (contains) {
float textScale = 1 / 128f;
GlStateManager.translated(position.x, position.y, position.z);
GlStateManager.translated(center.x, center.y, center.z);
GlStateManager.scaled(textScale, -textScale, textScale);
GlStateManager.rotated(AngleHelper.horizontalAngle(facing), 0, 1, 0);
GlStateManager.translated(17.5f, -5f, -5f);
GlStateManager.rotated(90, 1, 0, 0);
String text = Lang.translate("logistics.filter");
FontRenderer font = Minecraft.getInstance().fontRenderer;
font.drawString(text, 0, 0, 0x88FFBB);
GlStateManager.translated(0, 0, -1 / 4f);
font.drawString(text, 1, 1, 0x224433);
if (filterBlock.showsCount() && !actor.getFilter().isEmpty()) {
String count = actor.getFilter().getCount() + "";
GlStateManager.translated(-7 - font.getStringWidth(count), 10, 10 + 1 / 4f);
GlStateManager.scaled(1.5, 1.5, 1.5);
font.drawString(count, 0, 0, 0xEDEDED);
GlStateManager.translated(0, 0, -1 / 4f);
font.drawString(count, 1, 1, 0x4F4F4F);
}
}
GlStateManager.disableBlend();
GlStateManager.popMatrix();
GlStateManager.lineWidth(1);
TessellatorHelper.cleanUpAfterDrawing();
}
}

View file

@ -1,85 +0,0 @@
package com.simibubi.create.modules.logistics.block;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.modules.logistics.FrequencyHandler.Frequency;
import com.simibubi.create.modules.logistics.IHaveWireless;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntityType;
public abstract class LinkedTileEntity extends SyncedTileEntity implements IHaveWireless {
public Frequency frequencyFirst;
public Frequency frequencyLast;
public LinkedTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
frequencyFirst = new Frequency(ItemStack.EMPTY);
frequencyLast = new Frequency(ItemStack.EMPTY);
}
@Override
public void onLoad() {
super.onLoad();
if (world.isRemote)
return;
getHandler().addToNetwork(this);
}
@Override
public void remove() {
super.remove();
if (world.isRemote)
return;
getHandler().removeFromNetwork(this);
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.put("FrequencyFirst", frequencyFirst.getStack().write(new CompoundNBT()));
compound.put("FrequencyLast", frequencyLast.getStack().write(new CompoundNBT()));
return super.write(compound);
}
@Override
public void read(CompoundNBT compound) {
frequencyFirst = new Frequency(ItemStack.read(compound.getCompound("FrequencyFirst")));
frequencyLast = new Frequency(ItemStack.read(compound.getCompound("FrequencyLast")));
super.read(compound);
}
@Override
public void setFrequency(boolean first, ItemStack stack) {
stack = stack.copy();
stack.setCount(1);
ItemStack toCompare = first ? frequencyFirst.getStack() : frequencyLast.getStack();
boolean changed = !ItemStack.areItemsEqual(stack, toCompare)
|| !ItemStack.areItemStackTagsEqual(stack, toCompare);
if (changed)
getHandler().removeFromNetwork(this);
if (first)
frequencyFirst = new Frequency(stack);
else
frequencyLast = new Frequency(stack);
if (!changed)
return;
sendData();
getHandler().addToNetwork(this);
}
@Override
public Frequency getFrequencyFirst() {
return frequencyFirst;
}
@Override
public Frequency getFrequencyLast() {
return frequencyLast;
}
}

View file

@ -1,80 +0,0 @@
package com.simibubi.create.modules.logistics.block;
import org.apache.commons.lang3.tuple.Pair;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@SuppressWarnings("deprecation")
public class LinkedTileEntityRenderer extends TileEntityRenderer<LinkedTileEntity> {
@Override
public void render(LinkedTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
int destroyStage) {
BlockState state = tileEntityIn.getBlockState();
IBlockWithFrequency block = (IBlockWithFrequency) state.getBlock();
Direction facing = block.getFrequencyItemFacing(state);
float scale = block.getItemHitboxScale();
TessellatorHelper.prepareForDrawing();
Pair<Vec3d, Vec3d> itemPositions = block.getFrequencyItemPositions(state);
Vec3d first = itemPositions.getLeft();
Vec3d second = itemPositions.getRight();
BlockPos pos = tileEntityIn.getPos();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
renderFrequencyItem(tileEntityIn.frequencyFirst.getStack(), first, facing, scale - 2/16f);
renderFrequencyItem(tileEntityIn.frequencyLast.getStack(), second, facing, scale - 2/16f);
TessellatorHelper.cleanUpAfterDrawing();
}
private void renderFrequencyItem(ItemStack stack, Vec3d position, Direction facing, float scaleDiff) {
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
boolean vertical = facing.getAxis().isVertical();
IBakedModel modelWithOverrides = itemRenderer.getModelWithOverrides(stack);
boolean blockItem = modelWithOverrides.isGui3d();
float offX = 0;
float offY = vertical && !blockItem ? 0 : 0;
float offZ = !blockItem ? 1 / 4f + 2 * scaleDiff : 0;
if (vertical)
offZ = -offZ;
float rotX = vertical ? 90 : 0;
float rotY = vertical ? 0 : facing.getHorizontalAngle() + (blockItem ? 180 : 0);
float rotZ = vertical && facing == Direction.DOWN ? 180 : 0;
if (facing.getAxis() == Axis.X) {
rotY = -rotY;
}
float scale = !blockItem ? .25f : .5f;
scale *= 1 + 8 * scaleDiff;
GlStateManager.pushMatrix();
GlStateManager.translated(position.x, position.y, position.z);
GlStateManager.rotatef(rotZ, 0, 0, 1);
GlStateManager.rotatef(rotY, 0, 1, 0);
GlStateManager.rotatef(rotX, 1, 0, 0);
GlStateManager.scaled(scale, scale, scale);
GlStateManager.translatef(offX, offY, offZ);
itemRenderer.renderItem(stack, TransformType.FIXED);
GlStateManager.popMatrix();
}
}

View file

@ -1,67 +0,0 @@
package com.simibubi.create.modules.logistics.block;
import static net.minecraft.state.properties.BlockStateProperties.POWERED;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.modules.logistics.IReceiveWireless;
import com.simibubi.create.modules.logistics.ITransmitWireless;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
public class RedstoneBridgeTileEntity extends LinkedTileEntity
implements ITickableTileEntity, IReceiveWireless, ITransmitWireless {
public boolean receivedSignal;
public boolean transmittedSignal;
public RedstoneBridgeTileEntity() {
super(AllTileEntities.REDSTONE_BRIDGE.type);
}
@Override
public boolean getSignal() {
return transmittedSignal;
}
@Override
public void setSignal(boolean powered) {
receivedSignal = powered;
}
public void transmit(boolean signal) {
transmittedSignal = signal;
notifySignalChange();
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.putBoolean("Transmit", transmittedSignal);
return super.write(compound);
}
@Override
public void read(CompoundNBT compound) {
transmittedSignal = compound.getBoolean("Transmit");
super.read(compound);
}
@Override
public void tick() {
if (!getBlockState().get(RedstoneBridgeBlock.RECEIVER))
return;
if (world.isRemote)
return;
if (receivedSignal != getBlockState().get(POWERED)) {
world.setBlockState(pos, getBlockState().cycle(POWERED));
Direction attachedFace = getBlockState().get(BlockStateProperties.FACING).getOpposite();
BlockPos attachedPos = pos.offset(attachedFace);
world.notifyNeighbors(attachedPos, world.getBlockState(attachedPos).getBlock());
return;
}
}
}

View file

@ -1,13 +1,7 @@
package com.simibubi.create.modules.logistics.block;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -21,26 +15,22 @@ 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.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
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;
public class RedstoneBridgeBlock extends ProperDirectionalBlock implements IBlockWithFrequency {
public class RedstoneLinkBlock extends ProperDirectionalBlock {
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
public static final BooleanProperty RECEIVER = BooleanProperty.create("receiver");
private static final List<Pair<Vec3d, Vec3d>> itemPositions = new ArrayList<>(Direction.values().length);
public RedstoneBridgeBlock() {
public RedstoneLinkBlock() {
super(Properties.from(Blocks.DARK_OAK_LOG));
cacheItemPositions();
setDefaultState(getDefaultState().with(POWERED, false).with(RECEIVER, false));
}
@ -76,7 +66,7 @@ public class RedstoneBridgeBlock extends ProperDirectionalBlock implements IBloc
if (previouslyPowered != shouldPower) {
worldIn.setBlockState(pos, state.cycle(POWERED), 2);
RedstoneBridgeTileEntity te = (RedstoneBridgeTileEntity) worldIn.getTileEntity(pos);
RedstoneLinkTileEntity te = (RedstoneLinkTileEntity) worldIn.getTileEntity(pos);
if (te == null)
return;
te.transmit(!previouslyPowered);
@ -115,7 +105,7 @@ public class RedstoneBridgeBlock extends ProperDirectionalBlock implements IBloc
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new RedstoneBridgeTileEntity();
return new RedstoneLinkTileEntity();
}
@Override
@ -123,7 +113,7 @@ public class RedstoneBridgeBlock extends ProperDirectionalBlock implements IBloc
BlockRayTraceResult hit) {
if (player.isSneaking()) {
RedstoneBridgeTileEntity te = (RedstoneBridgeTileEntity) worldIn.getTileEntity(pos);
RedstoneLinkTileEntity te = (RedstoneLinkTileEntity) worldIn.getTileEntity(pos);
if (te == null)
return false;
@ -139,7 +129,7 @@ public class RedstoneBridgeBlock extends ProperDirectionalBlock implements IBloc
return true;
}
return handleActivatedFrequencySlots(state, worldIn, pos, player, handIn, hit);
return false;
}
@Override
@ -171,52 +161,6 @@ public class RedstoneBridgeBlock extends ProperDirectionalBlock implements IBloc
return AllShapes.REDSTONE_BRIDGE.get(state.get(FACING));
}
private void cacheItemPositions() {
if (!itemPositions.isEmpty())
return;
Vec3d first = Vec3d.ZERO;
Vec3d second = Vec3d.ZERO;
Vec3d shift = VecHelper.getCenterOf(BlockPos.ZERO);
float zFightOffset = 1 / 128f;
for (Direction facing : Direction.values()) {
if (facing.getAxis().isHorizontal()) {
first = new Vec3d(10 / 16f, 5.5f / 16f, 2f / 16f + zFightOffset);
second = new Vec3d(10 / 16f, 10.5f / 16f, 2f / 16f + zFightOffset);
float angle = facing.getHorizontalAngle();
if (facing.getAxis() == Axis.X)
angle = -angle;
first = VecHelper.rotate(first.subtract(shift), angle, Axis.Y).add(shift);
second = VecHelper.rotate(second.subtract(shift), angle, Axis.Y).add(shift);
} else {
first = new Vec3d(10 / 16f, 2f / 16f + zFightOffset, 5.5f / 16f);
second = new Vec3d(10 / 16f, 2f / 16f + zFightOffset, 10.5f / 16f);
if (facing == Direction.DOWN) {
first = VecHelper.rotate(first.subtract(shift), 180, Axis.X).add(shift);
second = VecHelper.rotate(second.subtract(shift), 180, Axis.X).add(shift);
}
}
itemPositions.add(Pair.of(first, second));
}
}
public Pair<Vec3d, Vec3d> getFrequencyItemPositions(BlockState state) {
Direction facing = state.get(FACING);
return itemPositions.get(facing.getIndex());
}
@Override
public Direction getFrequencyItemFacing(BlockState state) {
return state.get(FACING);
}
@Override
public PushReaction getPushReaction(BlockState state) {
return PushReaction.BLOCK;

View file

@ -0,0 +1,155 @@
package com.simibubi.create.modules.logistics.block;
import static net.minecraft.state.properties.BlockStateProperties.POWERED;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour.SlotPositioning;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
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.math.BlockPos;
import net.minecraft.util.math.Vec3d;
public class RedstoneLinkTileEntity extends SmartTileEntity {
private static LinkBehaviour.SlotPositioning slots;
private boolean receivedSignal;
private boolean transmittedSignal;
private LinkBehaviour link;
private boolean transmitter;
public RedstoneLinkTileEntity() {
super(AllTileEntities.REDSTONE_BRIDGE.type);
}
public RedstoneLinkTileEntity(boolean transmitter) {
this();
this.transmitter = transmitter;
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
}
@Override
public void addBehavioursDeferred(List<TileEntityBehaviour> behaviours) {
if (slots == null)
createSlotPositioning();
createLink();
behaviours.add(link);
}
protected void createLink() {
if (transmitter)
link = LinkBehaviour.transmitter(this, this::getSignal);
else
link = LinkBehaviour.receiver(this, this::setSignal);
link.withSlotPositioning(slots);
}
public boolean getSignal() {
return transmittedSignal;
}
public void setSignal(boolean powered) {
receivedSignal = powered;
}
public void transmit(boolean signal) {
transmittedSignal = signal;
link.notifySignalChange();
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.putBoolean("Transmitter", transmitter);
compound.putBoolean("Receive", receivedSignal);
compound.putBoolean("Transmit", transmittedSignal);
return super.write(compound);
}
@Override
public void read(CompoundNBT compound) {
transmitter = compound.getBoolean("Transmitter");
receivedSignal = compound.getBoolean("Receive");
transmittedSignal = compound.getBoolean("Transmit");
super.read(compound);
}
@Override
public void tick() {
super.tick();
if (isTransmitterBlock() != transmitter) {
transmitter = isTransmitterBlock();
LinkBehaviour prevlink = link;
removeBehaviour(LinkBehaviour.TYPE);
createLink();
link.copyItemsFrom(prevlink);
putBehaviour(link);
}
if (transmitter)
return;
if (world.isRemote)
return;
if (receivedSignal != getBlockState().get(POWERED)) {
world.setBlockState(pos, getBlockState().cycle(POWERED));
Direction attachedFace = getBlockState().get(BlockStateProperties.FACING).getOpposite();
BlockPos attachedPos = pos.offset(attachedFace);
world.notifyNeighbors(attachedPos, world.getBlockState(attachedPos).getBlock());
return;
}
}
protected Boolean isTransmitterBlock() {
return !getBlockState().get(RedstoneLinkBlock.RECEIVER);
}
protected void createSlotPositioning() {
slots = new SlotPositioning(state -> {
Direction facing = state.get(RedstoneLinkBlock.FACING);
Vec3d first = Vec3d.ZERO;
Vec3d second = Vec3d.ZERO;
if (facing.getAxis().isHorizontal()) {
first = VecHelper.voxelSpace(10f, 5.5f, 2.5f);
second = VecHelper.voxelSpace(10f, 10.5f, 2.5f);
float angle = facing.getHorizontalAngle();
if (facing.getAxis() == Axis.X)
angle = -angle;
first = VecHelper.rotateCentered(first, angle, Axis.Y);
second = VecHelper.rotateCentered(second, angle, Axis.Y);
} else {
first = VecHelper.voxelSpace(10f, 2.5f, 5.5f);
second = VecHelper.voxelSpace(10f, 2.5f, 10.5f);
if (facing == Direction.DOWN) {
first = VecHelper.rotateCentered(first, 180, Axis.X);
second = VecHelper.rotateCentered(second, 180, Axis.X);
}
}
return Pair.of(first, second);
}, state -> {
Direction facing = state.get(RedstoneLinkBlock.FACING);
float yRot = facing.getAxis().isVertical() ? 180 : AngleHelper.horizontalAngle(facing);
float zRot = facing == Direction.UP ? 90 : facing == Direction.DOWN ? 270 : 0;
return new Vec3d(0, yRot + 180, zRot);
}).scale(.5f);
}
}

View file

@ -0,0 +1,109 @@
package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IHaveNoBlockItem;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.logistics.block.transposer.TransposerBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.block.material.PushReaction;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
public abstract class AttachedLogisiticalBlock extends HorizontalBlock implements IHaveNoBlockItem {
public static final BooleanProperty UPWARD = BooleanProperty.create("upward");
public AttachedLogisiticalBlock() {
super(Properties.from(Blocks.ANDESITE));
}
@Override
public boolean hasBlockItem() {
return !isVertical();
}
protected abstract boolean isVertical();
protected abstract BlockState getVerticalDefaultState();
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState state = getDefaultState();
if (context.getFace().getAxis().isHorizontal()) {
state = state.with(HORIZONTAL_FACING, context.getFace().getOpposite());
} else {
state = getVerticalDefaultState();
state = state.with(UPWARD, context.getFace() != Direction.UP);
state = state.with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing());
}
return state;
}
@Override
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
Direction facing = getBlockFacing(state);
return canAttachToSide(worldIn, pos, facing);
}
protected boolean canAttachToSide(IWorldReader worldIn, BlockPos pos, Direction facing) {
BlockPos neighbourPos = pos.offset(facing);
BlockState neighbour = worldIn.getBlockState(neighbourPos);
if (neighbour.getBlock() instanceof TransposerBlock)
return false;
if (AllBlocks.BELT.typeOf(neighbour))
return BeltBlock.canAccessFromSide(facing, neighbour);
return !neighbour.getShape(worldIn, pos).isEmpty();
}
@Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
if (worldIn.isRemote)
return;
Direction blockFacing = getBlockFacing(state);
if (fromPos.equals(pos.offset(blockFacing))) {
if (!isValidPosition(state, worldIn, pos)) {
worldIn.destroyBlock(pos, true);
return;
}
}
}
public static Direction getBlockFacing(BlockState state) {
if (isVertical(state))
return state.get(UPWARD) ? Direction.UP : Direction.DOWN;
return state.get(HORIZONTAL_FACING);
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
if (isVertical())
builder.add(UPWARD);
super.fillStateContainer(builder.add(HORIZONTAL_FACING));
}
public static boolean isVertical(BlockState state) {
Block block = state.getBlock();
return ((block instanceof AttachedLogisiticalBlock)
&& (((AttachedLogisiticalBlock) state.getBlock())).isVertical());
}
@Override
public PushReaction getPushReaction(BlockState state) {
return PushReaction.BLOCK;
}
}

View file

@ -1,16 +0,0 @@
package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
public class BeltFunnelTileEntityRenderer extends TileEntityRenderer<BeltFunnelTileEntity> {
@Override
public void render(BeltFunnelTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
int destroyStage) {
super.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
FilteredTileEntityRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
}
}

View file

@ -1,11 +1,12 @@
package com.simibubi.create.modules.logistics.block.belts;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
@ -15,48 +16,37 @@ import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.block.IHaveFilterSlot;
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.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
public class EntityDetectorBlock extends HorizontalBlock
implements IWithTileEntity<EntityDetectorTileEntity>, IBeltAttachment, IHaveFilterSlot {
public class BeltObserverBlock extends HorizontalBlock
implements IWithTileEntity<BeltObserverTileEntity>, IBeltAttachment {
public static BooleanProperty POWERED = BlockStateProperties.POWERED;
public static BooleanProperty BELT = BooleanProperty.create("belt");
private static final List<Vec3d> itemPositions = new ArrayList<>(Direction.values().length);
public EntityDetectorBlock() {
public BeltObserverBlock() {
super(Properties.from(Blocks.ANDESITE));
setDefaultState(getDefaultState().with(POWERED, false).with(BELT, false));
cacheItemPositions();
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new EntityDetectorTileEntity();
return new BeltObserverTileEntity();
}
@Override
@ -140,8 +130,8 @@ public class EntityDetectorBlock extends HorizontalBlock
}
@Override
public boolean isAttachedCorrectly(IWorld world, BlockPos attachmentPos, BlockPos beltPos, BlockState attachmentState,
BlockState beltState) {
public boolean isAttachedCorrectly(IWorld world, BlockPos attachmentPos, BlockPos beltPos,
BlockState attachmentState, BlockState beltState) {
return attachmentState.get(BELT);
}
@ -160,12 +150,6 @@ public class EntityDetectorBlock extends HorizontalBlock
return side != state.get(HORIZONTAL_FACING).getOpposite();
}
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
return handleActivatedFilterSlots(state, worldIn, pos, player, handIn, hit);
}
@Override
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (newState.getBlock() != this || newState.with(POWERED, false) != state.with(POWERED, false))
@ -183,20 +167,16 @@ public class EntityDetectorBlock extends HorizontalBlock
@Override
public boolean startProcessingItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
state.processingDuration = 0;
withTileEntityDo(te.getWorld(), state.attachmentPos, detectorTE -> {
ItemStack filter = detectorTE.getFilter();
if (filter.isEmpty())
return;
// Todo: Package filters
if (!ItemStack.areItemsEqual(transported.stack, filter)) {
FilteringBehaviour behaviour = TileEntityBehaviour.get(te.getWorld(), state.attachmentPos,
FilteringBehaviour.TYPE);
if (behaviour != null) {
if (!behaviour.test(transported.stack)) {
state.processingDuration = -1;
return;
return false;
}
});
}
World world = te.getWorld();
BlockState blockState = world.getBlockState(state.attachmentPos);
if (state.processingDuration == 0) {
@ -205,31 +185,17 @@ public class EntityDetectorBlock extends HorizontalBlock
world.notifyNeighborsOfStateChange(state.attachmentPos, this);
return true;
}
return false;
}
@Override
public boolean processEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
if (te.getWorld().isRemote)
return false;
if (state.processingEntity != entity) {
state.processingEntity = entity;
state.processingDuration = 0;
withTileEntityDo(te.getWorld(), state.attachmentPos, detectorTE -> {
ItemStack filter = detectorTE.getFilter();
if (filter.isEmpty())
return;
// Todo: Package filters
if (!(entity instanceof ItemEntity)
|| !ItemStack.areItemsEqual(((ItemEntity) entity).getItem(), filter)) {
state.processingDuration = -1;
return;
}
});
}
if (entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos())) > .5f)
@ -247,7 +213,6 @@ public class EntityDetectorBlock extends HorizontalBlock
world.setBlockState(state.attachmentPos, blockState.with(POWERED, true));
world.getPendingBlockTicks().scheduleTick(state.attachmentPos, this, 6);
world.notifyNeighborsOfStateChange(state.attachmentPos, this);
return false;
}
@ -257,42 +222,4 @@ public class EntityDetectorBlock extends HorizontalBlock
worldIn.notifyNeighborsOfStateChange(pos, this);
}
private void cacheItemPositions() {
if (!itemPositions.isEmpty())
return;
Vec3d position = Vec3d.ZERO;
Vec3d shift = VecHelper.getCenterOf(BlockPos.ZERO);
float zFightOffset = 1 / 128f;
for (int i = 0; i < 4; i++) {
Direction facing = Direction.byHorizontalIndex(i);
position = new Vec3d(8f / 16f + zFightOffset, 15f / 16f, 17.75f / 16f);
float angle = facing.getHorizontalAngle();
if (facing.getAxis() == Axis.X)
angle = -angle;
position = VecHelper.rotate(position.subtract(shift), angle, Axis.Y).add(shift);
itemPositions.add(position);
}
}
@Override
public float getItemHitboxScale() {
return 1.76f / 16f;
}
@Override
public Vec3d getFilterPosition(BlockState state) {
Direction facing = state.get(HORIZONTAL_FACING);
return itemPositions.get(facing.getHorizontalIndex());
}
@Override
public Direction getFilterFacing(BlockState state) {
return state.get(HORIZONTAL_FACING);
}
}

View file

@ -0,0 +1,45 @@
package com.simibubi.create.modules.logistics.block.belts;
import java.util.List;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.SlotPositioning;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.Vec3d;
public class BeltObserverTileEntity extends SmartTileEntity {
private static FilteringBehaviour.SlotPositioning slots;
private FilteringBehaviour filtering;
public BeltObserverTileEntity() {
super(AllTileEntities.ENTITY_DETECTOR.type);
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
if (slots == null)
createSlotPositioning();
filtering = new FilteringBehaviour(this).withSlotPositioning(slots).moveText(new Vec3d(0, 5, 0));
behaviours.add(filtering);
}
protected void createSlotPositioning() {
slots = new SlotPositioning(state -> {
float yRot = AngleHelper.horizontalAngle(state.get(HorizontalBlock.HORIZONTAL_FACING));
Vec3d position = VecHelper.voxelSpace(8f, 14.5f, 16f);
return VecHelper.rotateCentered(position, yRot, Axis.Y);
}, state -> {
float yRot = AngleHelper.horizontalAngle(state.get(HorizontalBlock.HORIZONTAL_FACING));
return new Vec3d(0, 180 + yRot, 90);
}).scale(.4f);
}
}

View file

@ -1,15 +1,15 @@
package com.simibubi.create.modules.logistics.block.belts;
import com.mojang.blaze3d.platform.GLX;
import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer;
import com.simibubi.create.foundation.behaviour.filtering.FilteringRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.state.properties.BlockStateProperties;
public class EntityDetectorTileEntityRenderer extends TileEntityRenderer<EntityDetectorTileEntity> {
public class BeltObserverTileEntityRenderer extends TileEntityRenderer<BeltObserverTileEntity> {
@Override
public void render(EntityDetectorTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
public void render(BeltObserverTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
int destroyStage) {
super.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
@ -19,7 +19,7 @@ public class EntityDetectorTileEntityRenderer extends TileEntityRenderer<EntityD
int k = i / 65536;
GLX.glMultiTexCoord2f(GLX.GL_TEXTURE1, (float) j, (float) k);
FilteredTileEntityRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
FilteringRenderer.renderOnTileEntity(tileEntityIn, x, y, z, partialTicks, destroyStage);
}
}

View file

@ -1,43 +0,0 @@
package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.modules.logistics.block.IHaveFilter;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
public class EntityDetectorTileEntity extends SyncedTileEntity implements IHaveFilter {
private ItemStack filter;
public EntityDetectorTileEntity() {
super(AllTileEntities.ENTITY_DETECTOR.type);
filter = ItemStack.EMPTY;
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.put("Filter", filter.serializeNBT());
return super.write(compound);
}
@Override
public void read(CompoundNBT compound) {
filter = ItemStack.read(compound.getCompound("Filter"));
super.read(compound);
}
@Override
public void setFilter(ItemStack stack) {
filter = stack.copy();
markDirty();
sendData();
}
@Override
public ItemStack getFilter() {
return filter.copy();
}
}

View file

@ -1,202 +0,0 @@
package com.simibubi.create.modules.logistics.block.belts;
import java.util.ArrayList;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.logistics.block.IExtractor;
import com.simibubi.create.modules.logistics.block.IHaveFilterSlot;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
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;
public class ExtractorBlock extends HorizontalBlock implements IHaveFilterSlot {
public static BooleanProperty POWERED = BlockStateProperties.POWERED;
protected static final List<Vec3d> filterLocations = new ArrayList<>();
public ExtractorBlock() {
super(Properties.from(Blocks.ANDESITE));
setDefaultState(getDefaultState().with(POWERED, false));
cacheFilterLocations();
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(HORIZONTAL_FACING, POWERED);
super.fillStateContainer(builder);
}
@Override
public boolean showsCount() {
return true;
}
@Override
public boolean hasTileEntity(BlockState state) {
return true;
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new ExtractorTileEntity();
}
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
return handleActivatedFilterSlots(state, worldIn, pos, player, handIn, hit);
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState state = getDefaultState();
if (context.getFace().getAxis().isHorizontal()) {
state = state.with(HORIZONTAL_FACING, context.getFace().getOpposite());
} else {
state = AllBlocks.VERTICAL_EXTRACTOR.get().getDefaultState();
state = state.with(VerticalExtractorBlock.UPWARD, context.getFace() != Direction.UP);
state = state.with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing());
}
return state.with(POWERED, Boolean.valueOf(context.getWorld().isBlockPowered(context.getPos())));
}
@Override
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
updateObservedInventory(state, worldIn, pos);
}
@Override
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
Direction facing = getBlockFacing(state);
BlockPos neighbourPos = pos.offset(facing);
BlockState neighbour = worldIn.getBlockState(neighbourPos);
if (AllBlocks.BELT.typeOf(neighbour)) {
return BeltBlock.canAccessFromSide(facing, neighbour);
}
return !neighbour.getShape(worldIn, pos).isEmpty();
}
@Override
public void onNeighborChange(BlockState state, IWorldReader world, BlockPos pos, BlockPos neighbor) {
if (world.isRemote())
return;
if (!isObserving(state, pos, neighbor))
return;
updateObservedInventory(state, world, pos);
}
private void updateObservedInventory(BlockState state, IWorldReader world, BlockPos pos) {
IExtractor extractor = (IExtractor) world.getTileEntity(pos);
if (extractor == null)
return;
extractor.neighborChanged();
}
private boolean isObserving(BlockState state, BlockPos pos, BlockPos observing) {
return observing.equals(pos.offset(getBlockFacing(state)));
}
@Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
if (worldIn.isRemote)
return;
Direction blockFacing = getBlockFacing(state);
if (fromPos.equals(pos.offset(blockFacing))) {
if (!isValidPosition(state, worldIn, pos)) {
worldIn.destroyBlock(pos, true);
return;
}
}
boolean previouslyPowered = state.get(POWERED);
if (previouslyPowered != worldIn.isBlockPowered(pos)) {
worldIn.setBlockState(pos, state.cycle(POWERED), 2);
IExtractor extractor = (IExtractor) worldIn.getTileEntity(pos);
if (extractor == null)
return;
extractor.setLocked(!previouslyPowered);
}
}
public Direction getBlockFacing(BlockState state) {
return state.get(HORIZONTAL_FACING);
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return AllShapes.EXTRACTOR.get(getBlockFacing(state));
}
private void cacheFilterLocations() {
filterLocations.clear();
float e = 1 / 128f;
Vec3d offsetForHorizontal = new Vec3d(8f / 16f, 10.5f / 16f + e, 2f / 16f);
Vec3d offsetForUpward = new Vec3d(8f / 16f, 14.15f / 16f - e, 12.75f / 16f);
Vec3d offsetForDownward = new Vec3d(8f / 16f, 1.85f / 16f + e, 12.75f / 16f);
for (Vec3d offset : new Vec3d[] { offsetForHorizontal, offsetForUpward, offsetForDownward }) {
for (int i = 0; i < 4; i++) {
Direction facing = Direction.byHorizontalIndex(i);
float angle = AngleHelper.horizontalAngle(facing);
filterLocations.add(VecHelper.rotateCentered(offset, angle, Axis.Y));
}
}
}
@Override
public float getItemHitboxScale() {
return 1.76f / 16f;
}
@Override
public Vec3d getFilterPosition(BlockState state) {
Direction facing = state.get(HORIZONTAL_FACING).getOpposite();
return filterLocations.get(facing.getHorizontalIndex());
}
@Override
public Direction getFilterFacing(BlockState state) {
return state.get(HORIZONTAL_FACING).getOpposite();
}
@Override
public PushReaction getPushReaction(BlockState state) {
return PushReaction.BLOCK;
}
public float getFilterAngle(BlockState state) {
return getBlockFacing(state).getAxis().isHorizontal() ? 0 : 90;
}
}

View file

@ -1,16 +0,0 @@
package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
public class ExtractorTileEntityRenderer extends TileEntityRenderer<ExtractorTileEntity> {
@Override
public void render(ExtractorTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
int destroyStage) {
super.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
FilteredTileEntityRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
}
}

View file

@ -1,37 +1,27 @@
package com.simibubi.create.modules.logistics.block.belts;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.AllShapes;
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.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.block.IHaveFilterSlot;
import com.simibubi.create.modules.logistics.block.IInventoryManipulator;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
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;
@ -39,11 +29,16 @@ import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, IWithTileEntity<BeltFunnelTileEntity>, IHaveFilterSlot {
public class FunnelBlock extends AttachedLogisiticalBlock
implements IBeltAttachment, IWithTileEntity<FunnelTileEntity> {
public BeltFunnelBlock() {
super(Properties.from(Blocks.ANDESITE));
cacheItemPositions();
public static final BooleanProperty BELT = BooleanProperty.create("belt");
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
if (!isVertical())
builder.add(BELT);
super.fillStateContainer(builder);
}
@Override
@ -51,6 +46,21 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
return true;
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new FunnelTileEntity();
}
@Override
protected boolean isVertical() {
return false;
}
@Override
protected BlockState getVerticalDefaultState() {
return AllBlocks.VERTICAL_FUNNEL.getDefault();
}
@Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
@ -64,44 +74,34 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
}
@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 boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
BlockPos neighbourPos = pos.offset(state.get(HORIZONTAL_FACING));
BlockState neighbour = worldIn.getBlockState(neighbourPos);
if (AllBlocks.BELT.typeOf(neighbour)) {
return BeltBlock.canAccessFromSide(state.get(HORIZONTAL_FACING), neighbour);
}
return !neighbour.getShape(worldIn, pos).isEmpty();
public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn,
BlockPos currentPos, BlockPos facingPos) {
if (facing == Direction.DOWN && !isVertical(stateIn))
return stateIn.with(BELT, isOnBelt(worldIn, currentPos));
return stateIn;
}
@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());
BlockState state = super.getStateForPlacement(context);
if (!isVertical(state)) {
World world = context.getWorld();
BlockPos pos = context.getPos();
state = state.with(BELT, isOnBelt(world, pos));
}
return state;
}
protected boolean isOnBelt(IWorld world, BlockPos pos) {
return AllBlocks.BELT.typeOf(world.getBlockState(pos.down()));
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return AllShapes.FUNNEL.get(state.get(HORIZONTAL_FACING));
Direction direction = getBlockFacing(state);
if (!isVertical(state) && state.get(BELT))
return AllShapes.BELT_FUNNEL.get(direction);
return AllShapes.FUNNEL.get(direction);
}
@Override
@ -147,80 +147,37 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
return process(te, transported, state);
}
@Override
public boolean isAttachedCorrectly(IWorld world, BlockPos attachmentPos, BlockPos beltPos,
BlockState attachmentState, BlockState beltState) {
return !isVertical(attachmentState);
}
@Override
public boolean processItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
Direction movementFacing = te.getMovementFacing();
if (movementFacing.getAxis() == Axis.Z)
movementFacing = movementFacing.getOpposite();
if (movementFacing != te.getWorld().getBlockState(state.attachmentPos)
.get(HORIZONTAL_FACING))
if (movementFacing != te.getWorld().getBlockState(state.attachmentPos).get(HORIZONTAL_FACING))
return false;
return process(te, transported, state);
}
public boolean process(BeltTileEntity belt, TransportedItemStack transported, BeltAttachmentState state) {
TileEntity te = belt.getWorld().getTileEntity(state.attachmentPos);
if (te == null || !(te instanceof BeltFunnelTileEntity))
if (te == null || !(te instanceof FunnelTileEntity))
return false;
BeltFunnelTileEntity funnel = (BeltFunnelTileEntity) te;
FunnelTileEntity funnel = (FunnelTileEntity) te;
ItemStack stack = funnel.tryToInsert(transported.stack);
transported.stack = stack;
return true;
}
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
return handleActivatedFilterSlots(state, worldIn, pos, player, handIn, hit);
}
private static final List<Vec3d> itemPositions = new ArrayList<>(Direction.values().length);
private void cacheItemPositions() {
itemPositions.clear();
Vec3d position = Vec3d.ZERO;
Vec3d shift = VecHelper.getCenterOf(BlockPos.ZERO);
float zFightOffset = 1 / 128f;
for (int i = 0; i < 4; i++) {
Direction facing = Direction.byHorizontalIndex(i);
position = new Vec3d(8f / 16f + zFightOffset, 9f / 16f, 2.25f / 16f);
float angle = facing.getHorizontalAngle();
if (facing.getAxis() == Axis.X)
angle = -angle;
position = VecHelper.rotate(position.subtract(shift), angle, Axis.Y).add(shift);
itemPositions.add(position);
public static class Vertical extends FunnelBlock {
@Override
protected boolean isVertical() {
return true;
}
}
@Override
public boolean showsCount() {
return true;
}
@Override
public float getItemHitboxScale() {
return 1.76f / 16f;
}
@Override
public Vec3d getFilterPosition(BlockState state) {
Direction facing = state.get(HORIZONTAL_FACING).getOpposite();
return itemPositions.get(facing.getHorizontalIndex());
}
@Override
public Direction getFilterFacing(BlockState state) {
return state.get(HORIZONTAL_FACING).getOpposite();
}
@Override
public PushReaction getPushReaction(BlockState state) {
return PushReaction.BLOCK;
}
}

View file

@ -1,11 +1,17 @@
package com.simibubi.create.modules.logistics.block.belts;
import java.util.List;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.SlotPositioning;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.ItemHandlerBeltSegment;
import com.simibubi.create.modules.logistics.block.IHaveFilter;
import com.simibubi.create.modules.logistics.block.IInventoryManipulator;
import com.simibubi.create.modules.logistics.block.extractor.ExtractorBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
@ -13,6 +19,8 @@ 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.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
@ -22,41 +30,44 @@ import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
public class BeltFunnelTileEntity extends SyncedTileEntity
implements ITickableTileEntity, IInventoryManipulator, IHaveFilter {
public class FunnelTileEntity extends SmartTileEntity implements ITickableTileEntity, IInventoryManipulator {
private static FilteringBehaviour.SlotPositioning slots;
private FilteringBehaviour filtering;
private LazyOptional<IItemHandler> inventory;
protected boolean waitingForInventorySpace;
private boolean initialize;
private ItemStack filter;
private ItemStack justEaten;
public BeltFunnelTileEntity() {
public FunnelTileEntity() {
super(AllTileEntities.BELT_FUNNEL.type);
inventory = LazyOptional.empty();
filter = ItemStack.EMPTY;
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
if (slots == null)
createSlotPositioning();
filtering = new FilteringBehaviour(this).withCallback(this::filterChanged).withSlotPositioning(slots);
behaviours.add(filtering);
}
public void filterChanged(ItemStack stack) {
neighborChanged();
}
@Override
public void read(CompoundNBT compound) {
filter = ItemStack.read(compound.getCompound("Filter"));
waitingForInventorySpace = compound.getBoolean("Waiting");
super.read(compound);
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.put("Filter", filter.serializeNBT());
compound.putBoolean("Waiting", waitingForInventorySpace);
return super.write(compound);
}
@Override
public void onLoad() {
initialize = true;
}
@Override
public CompoundNBT writeToClient(CompoundNBT tag) {
if (justEaten != null) {
@ -87,16 +98,18 @@ public class BeltFunnelTileEntity extends SyncedTileEntity
@Override
public void tick() {
if (initialize && hasWorld()) {
neighborChanged();
initialize = false;
}
if (world.isRemote && justEaten != null) {
spawnParticles(justEaten);
justEaten = null;
}
}
@Override
public void initialize() {
neighborChanged();
super.initialize();
}
@Override
public void setInventory(LazyOptional<IItemHandler> inventory) {
this.inventory = inventory;
@ -115,26 +128,19 @@ public class BeltFunnelTileEntity extends SyncedTileEntity
return stack;
if (waitingForInventorySpace && !(inventory.orElse(null) instanceof ItemHandlerBeltSegment))
return stack;
if (!filter.isEmpty() && !ItemStack.areItemsEqual(filter, stack))
if (!filtering.test(stack))
return stack;
IItemHandler inv = inventory.orElse(null);
ItemStack inserted = stack.copy();
int amountToExtract = Math.min(filter.isEmpty() ? 64 : filter.getCount(), stack.getCount());
inserted.setCount(amountToExtract);
ItemStack remainder = ItemHandlerHelper.insertItemStacked(inv, inserted, false);
waitingForInventorySpace = true;
if (remainder.isEmpty()) {
if (!world.isRemote)
world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_EAT, SoundCategory.BLOCKS, .125f, 1f);
justEaten = stack.copy();
remainder = stack.copy();
remainder.setCount(stack.getCount() - amountToExtract);
} else {
waitingForInventorySpace = true;
remainder.grow(stack.getCount() - amountToExtract);
waitingForInventorySpace = false;
}
sendData();
@ -150,17 +156,35 @@ public class BeltFunnelTileEntity extends SyncedTileEntity
1 / 6f, zSpeed);
}
@Override
public void setFilter(ItemStack stack) {
filter = stack.copy();
markDirty();
sendData();
neighborChanged();
}
protected void createSlotPositioning() {
slots = new SlotPositioning(state -> {
Vec3d offsetForHorizontal = VecHelper.voxelSpace(8f, 14f, 13.5f);
Vec3d offsetForBelt = VecHelper.voxelSpace(8f, 8.5f, 14f);
Vec3d offsetForUpward = VecHelper.voxelSpace(8f, 13.5f, 2f);
Vec3d offsetForDownward = VecHelper.voxelSpace(8f, 2.5f, 2f);
Vec3d vec = offsetForHorizontal;
@Override
public ItemStack getFilter() {
return filter.copy();
float yRot = AngleHelper.horizontalAngle(state.get(ExtractorBlock.HORIZONTAL_FACING));
if (AttachedLogisiticalBlock.isVertical(state))
vec = state.get(AttachedLogisiticalBlock.UPWARD) ? offsetForUpward : offsetForDownward;
else if (state.get(FunnelBlock.BELT))
vec = offsetForBelt;
return VecHelper.rotateCentered(vec, yRot, Axis.Y);
}, state -> {
Direction blockFacing = AttachedLogisiticalBlock.getBlockFacing(state);
boolean vertical = AttachedLogisiticalBlock.isVertical(state);
float horizontalAngle = AngleHelper.horizontalAngle(state.get(ExtractorBlock.HORIZONTAL_FACING));
float yRot = blockFacing == Direction.DOWN ? horizontalAngle + 180 : horizontalAngle;
float zRot = (vertical || state.get(FunnelBlock.BELT)) ? 90 : 0;
if (blockFacing == Direction.UP)
zRot += 180;
return new Vec3d(0, yRot, zRot);
}).scale(.4f);
}
}

View file

@ -1,135 +0,0 @@
package com.simibubi.create.modules.logistics.block.belts;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.logistics.block.IBlockWithFrequency;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext;
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.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
public class LinkedExtractorBlock extends ExtractorBlock implements IBlockWithFrequency {
private static final List<Pair<Vec3d, Vec3d>> linkItemLocations = new ArrayList<>();
public LinkedExtractorBlock() {
super();
cacheLinkItemLocations();
}
@Override
public BlockRenderLayer getRenderLayer() {
return BlockRenderLayer.CUTOUT;
}
@Override
public boolean hasTileEntity(BlockState state) {
return true;
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new LinkedExtractorTileEntity();
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState state = getDefaultState();
if (context.getFace().getAxis().isHorizontal()) {
state = state.with(HORIZONTAL_FACING, context.getFace().getOpposite());
} else {
state = AllBlocks.VERTICAL_LINKED_EXTRACTOR.get().getDefaultState();
state = state.with(VerticalExtractorBlock.UPWARD, context.getFace() != Direction.UP);
state = state.with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing());
}
return state.with(POWERED, Boolean.valueOf(false));
}
@Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
if (worldIn.isRemote)
return;
Direction blockFacing = getBlockFacing(state);
if (fromPos.equals(pos.offset(blockFacing))) {
if (!isValidPosition(state, worldIn, pos)) {
worldIn.destroyBlock(pos, true);
return;
}
}
}
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
return super.onBlockActivated(state, worldIn, pos, player, handIn, hit)
|| handleActivatedFrequencySlots(state, worldIn, pos, player, handIn, hit);
}
private void cacheLinkItemLocations() {
linkItemLocations.clear();
float zFightOffset = 1 / 128f;
Vec3d first = new Vec3d(11.5f / 16f + zFightOffset, 4f / 16f, 14f / 16f);
Vec3d second = new Vec3d(11.5f / 16f + zFightOffset, 8f / 16f, 14f / 16f);
Vec3d firstUpward = new Vec3d(10f / 16f + zFightOffset, 14f / 16f, 11.5f / 16f);
Vec3d secondUpward = new Vec3d(6f / 16f + zFightOffset, 14f / 16f, 11.5f / 16f);
Vec3d firstDownward = new Vec3d(10f / 16f + zFightOffset, 2f / 16f, 11.5f / 16f);
Vec3d secondDownward = new Vec3d(6f / 16f + zFightOffset, 2f / 16f, 11.5f / 16f);
cacheForAllSides(first, second);
cacheForAllSides(firstUpward, secondUpward);
cacheForAllSides(firstDownward, secondDownward);
}
private void cacheForAllSides(Vec3d first, Vec3d second) {
for (int i = 0; i < 4; i++) {
Direction facing = Direction.byHorizontalIndex(i);
float angle = AngleHelper.horizontalAngle(facing);
linkItemLocations.add(Pair.of(VecHelper.rotateCentered(first, angle, Axis.Y),
VecHelper.rotateCentered(second, angle, Axis.Y)));
}
}
@Override
public float getItemHitboxScale() {
return 3 / 32f;
}
@Override
public Pair<Vec3d, Vec3d> getFrequencyItemPositions(BlockState state) {
Direction facing = state.get(HORIZONTAL_FACING);
Direction extractorFacing = getBlockFacing(state);
int groupOffset = extractorFacing == Direction.UP ? 4 : extractorFacing == Direction.DOWN ? 8 : 0;
return linkItemLocations.get(groupOffset + facing.getHorizontalIndex());
}
@Override
public Direction getFrequencyItemFacing(BlockState state) {
if (getBlockFacing(state).getAxis().isHorizontal())
return state.get(HORIZONTAL_FACING).rotateYCCW();
return state.get(HORIZONTAL_FACING);
}
}

View file

@ -1,142 +0,0 @@
package com.simibubi.create.modules.logistics.block.belts;
import static net.minecraft.state.properties.BlockStateProperties.POWERED;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.modules.logistics.IReceiveWireless;
import com.simibubi.create.modules.logistics.block.IExtractor;
import com.simibubi.create.modules.logistics.block.IHaveFilter;
import com.simibubi.create.modules.logistics.block.LinkedTileEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
public class LinkedExtractorTileEntity extends LinkedTileEntity
implements IReceiveWireless, ITickableTileEntity, IExtractor, IHaveFilter {
public boolean receivedSignal;
private State state;
private ItemStack filter;
private int cooldown;
private LazyOptional<IItemHandler> inventory;
private boolean initialize;
public LinkedExtractorTileEntity() {
super(AllTileEntities.LINKED_EXTRACTOR.type);
setState(State.ON_COOLDOWN);
inventory = LazyOptional.empty();
filter = ItemStack.EMPTY;
}
@Override
public void onLoad() {
super.onLoad();
initialize = true;
}
@Override
public World getWirelessWorld() {
return super.getWorld();
}
@Override
public void setSignal(boolean powered) {
receivedSignal = powered;
}
@Override
public void read(CompoundNBT compound) {
filter = ItemStack.read(compound.getCompound("Filter"));
if (compound.getBoolean("Locked"))
setState(State.LOCKED);
super.read(compound);
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.put("Filter", filter.serializeNBT());
compound.putBoolean("Locked", getState() == State.LOCKED);
return super.write(compound);
}
@Override
public void tick() {
if (initialize && hasWorld()) {
if (world.isBlockPowered(pos))
state = State.LOCKED;
neighborChanged();
initialize = false;
}
IExtractor.super.tick();
if (world.isRemote)
return;
if (receivedSignal != getBlockState().get(POWERED)) {
setLocked(receivedSignal);
world.setBlockState(pos, getBlockState().cycle(POWERED));
return;
}
}
@Override
public State getState() {
return state;
}
@Override
public void setState(State state) {
if (state == State.ON_COOLDOWN)
cooldown = CreateConfig.parameters.extractorDelay.get();
if (state == State.WAITING_FOR_INVENTORY)
cooldown = CreateConfig.parameters.extractorInventoryScanDelay.get();
this.state = state;
}
@Override
public int tickCooldown() {
return cooldown--;
}
@Override
public BlockPos getInventoryPos() {
BlockState blockState = getBlockState();
Block block = blockState.getBlock();
if (!(block instanceof ExtractorBlock))
return null;
return getPos().offset(((ExtractorBlock) block).getBlockFacing(blockState));
}
@Override
public LazyOptional<IItemHandler> getInventory() {
return inventory;
}
@Override
public void setInventory(LazyOptional<IItemHandler> inventory) {
this.inventory = inventory;
}
@Override
public void setFilter(ItemStack stack) {
filter = stack.copy();
markDirty();
sendData();
neighborChanged();
}
@Override
public ItemStack getFilter() {
return filter.copy();
}
}

View file

@ -1,24 +0,0 @@
package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.LinkedTileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
public class LinkedExtractorTileEntityRenderer extends TileEntityRenderer<LinkedExtractorTileEntity> {
LinkedTileEntityRenderer linkRenderer;
public LinkedExtractorTileEntityRenderer() {
linkRenderer = new LinkedTileEntityRenderer();
}
@Override
public void render(LinkedExtractorTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
int destroyStage) {
super.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
linkRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
FilteredTileEntityRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
}
}

View file

@ -1,44 +0,0 @@
package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IHaveNoBlockItem;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d;
public class VerticalExtractorBlock extends ExtractorBlock implements IHaveNoBlockItem {
public static BooleanProperty UPWARD = BooleanProperty.create("upward");
public VerticalExtractorBlock() {
super();
setDefaultState(getDefaultState().with(UPWARD, true));
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
super.fillStateContainer(builder.add(UPWARD));
}
@Override
public Direction getBlockFacing(BlockState state) {
return state.get(UPWARD) ? Direction.UP : Direction.DOWN;
}
@Override
public ResourceLocation getLootTable() {
return AllBlocks.EXTRACTOR.get().getLootTable();
}
@Override
public Vec3d getFilterPosition(BlockState state) {
Direction facing = state.get(HORIZONTAL_FACING).getOpposite();
return filterLocations.get((state.get(UPWARD) ? 4 : 8) + facing.getHorizontalIndex());
}
}

View file

@ -1,44 +0,0 @@
package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IHaveNoBlockItem;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d;
public class VerticalLinkedExtractorBlock extends LinkedExtractorBlock implements IHaveNoBlockItem {
public static BooleanProperty UPWARD = BooleanProperty.create("upward");
public VerticalLinkedExtractorBlock() {
super();
setDefaultState(getDefaultState().with(UPWARD, true));
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
super.fillStateContainer(builder.add(UPWARD));
}
@Override
public Direction getBlockFacing(BlockState state) {
return state.get(UPWARD) ? Direction.UP : Direction.DOWN;
}
@Override
public ResourceLocation getLootTable() {
return AllBlocks.LINKED_EXTRACTOR.get().getLootTable();
}
@Override
public Vec3d getFilterPosition(BlockState state) {
Direction facing = state.get(HORIZONTAL_FACING).getOpposite();
return filterLocations.get((state.get(UPWARD) ? 4 : 8) + facing.getHorizontalIndex());
}
}

View file

@ -0,0 +1,148 @@
package com.simibubi.create.modules.logistics.block.extractor;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.logistics.block.IExtractor;
import com.simibubi.create.modules.logistics.block.belts.AttachedLogisiticalBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
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;
public class ExtractorBlock extends AttachedLogisiticalBlock {
public static BooleanProperty POWERED = BlockStateProperties.POWERED;
public ExtractorBlock() {
super();
setDefaultState(getDefaultState().with(POWERED, false));
}
@Override
protected boolean isVertical() {
return false;
}
@Override
protected BlockState getVerticalDefaultState() {
return AllBlocks.VERTICAL_EXTRACTOR.getDefault();
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
super.fillStateContainer(builder.add(POWERED));
}
@Override
public boolean hasTileEntity(BlockState state) {
return true;
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new ExtractorTileEntity();
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
return super.getStateForPlacement(context).with(POWERED,
reactsToRedstone() && context.getWorld().isBlockPowered(context.getPos()));
}
@Override
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
updateObservedInventory(state, worldIn, pos);
}
@Override
public void onNeighborChange(BlockState state, IWorldReader world, BlockPos pos, BlockPos neighbor) {
if (world.isRemote())
return;
if (!isObserving(state, pos, neighbor))
return;
updateObservedInventory(state, world, pos);
}
private void updateObservedInventory(BlockState state, IWorldReader world, BlockPos pos) {
IExtractor extractor = (IExtractor) world.getTileEntity(pos);
if (extractor == null)
return;
extractor.neighborChanged();
}
private boolean isObserving(BlockState state, BlockPos pos, BlockPos observing) {
return observing.equals(pos.offset(getBlockFacing(state)));
}
@Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
super.neighborChanged(state, worldIn, pos, blockIn, fromPos, isMoving);
if (worldIn.isRemote)
return;
if (!reactsToRedstone())
return;
boolean previouslyPowered = state.get(POWERED);
if (previouslyPowered != worldIn.isBlockPowered(pos)) {
worldIn.setBlockState(pos, state.cycle(POWERED), 2);
IExtractor extractor = (IExtractor) worldIn.getTileEntity(pos);
if (extractor == null)
return;
extractor.setLocked(!previouslyPowered);
}
}
protected boolean reactsToRedstone() {
return true;
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return AllShapes.EXTRACTOR.get(getBlockFacing(state));
}
public static Vec3d getFilterSlotPosition(BlockState state) {
float verticalOffset = (state.getBlock() instanceof ExtractorBlock) ? 10.5f : 12.5f;
Vec3d offsetForHorizontal = VecHelper.voxelSpace(8f, verticalOffset, 14f);
Vec3d offsetForUpward = VecHelper.voxelSpace(8f, 14.15f, 3.5f);
Vec3d offsetForDownward = VecHelper.voxelSpace(8f, 1.85f, 3.5f);
Vec3d vec = offsetForHorizontal;
float yRot = AngleHelper.horizontalAngle(state.get(ExtractorBlock.HORIZONTAL_FACING));
if (AttachedLogisiticalBlock.isVertical(state))
vec = state.get(AttachedLogisiticalBlock.UPWARD) ? offsetForUpward : offsetForDownward;
return VecHelper.rotateCentered(vec, yRot, Axis.Y);
}
public static Vec3d getFilterSlotOrientation(BlockState state) {
float yRot = AngleHelper.horizontalAngle(state.get(ExtractorBlock.HORIZONTAL_FACING));
float zRot = (AttachedLogisiticalBlock.isVertical(state)) ? 0 : 90;
return new Vec3d(0, yRot, zRot);
}
public static class Vertical extends ExtractorBlock {
@Override
protected boolean isVertical() {
return true;
}
}
}

View file

@ -1,34 +1,58 @@
package com.simibubi.create.modules.logistics.block.belts;
package com.simibubi.create.modules.logistics.block.extractor;
import java.util.List;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.SlotPositioning;
import com.simibubi.create.modules.logistics.block.IExtractor;
import com.simibubi.create.modules.logistics.block.IHaveFilter;
import com.simibubi.create.modules.logistics.block.belts.AttachedLogisiticalBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
public class ExtractorTileEntity extends SyncedTileEntity implements IExtractor, ITickableTileEntity, IHaveFilter {
public class ExtractorTileEntity extends SmartTileEntity implements IExtractor, ITickableTileEntity {
private static FilteringBehaviour.SlotPositioning slots;
private State state;
private ItemStack filter;
private int cooldown;
private LazyOptional<IItemHandler> inventory;
private boolean initialize;
private FilteringBehaviour filtering;
public ExtractorTileEntity() {
super(AllTileEntities.EXTRACTOR.type);
this(AllTileEntities.EXTRACTOR.type);
}
protected ExtractorTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
state = State.ON_COOLDOWN;
cooldown = CreateConfig.parameters.extractorDelay.get();
inventory = LazyOptional.empty();
filter = ItemStack.EMPTY;
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
if (slots == null)
slots = new SlotPositioning(ExtractorBlock::getFilterSlotPosition, ExtractorBlock::getFilterSlotOrientation)
.scale(.4f);
filtering = new FilteringBehaviour(this).withCallback(this::filterChanged).withSlotPositioning(slots)
.showCount();
behaviours.add(filtering);
}
public void filterChanged(ItemStack stack) {
neighborChanged();
}
@Override
@ -38,7 +62,6 @@ public class ExtractorTileEntity extends SyncedTileEntity implements IExtractor,
@Override
public void read(CompoundNBT compound) {
filter = ItemStack.read(compound.getCompound("Filter"));
if (compound.getBoolean("Locked"))
setState(State.LOCKED);
super.read(compound);
@ -46,24 +69,21 @@ public class ExtractorTileEntity extends SyncedTileEntity implements IExtractor,
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.put("Filter", filter.serializeNBT());
compound.putBoolean("Locked", getState() == State.LOCKED);
return super.write(compound);
}
@Override
public void onLoad() {
initialize = true;
public void initialize() {
super.initialize();
if (world.isBlockPowered(pos))
state = State.LOCKED;
neighborChanged();
}
@Override
public void tick() {
if (initialize && hasWorld()) {
if (world.isBlockPowered(pos))
state = State.LOCKED;
neighborChanged();
initialize = false;
}
super.tick();
IExtractor.super.tick();
}
@ -87,7 +107,7 @@ public class ExtractorTileEntity extends SyncedTileEntity implements IExtractor,
Block block = blockState.getBlock();
if (!(block instanceof ExtractorBlock))
return null;
return getPos().offset(((ExtractorBlock) block).getBlockFacing(blockState));
return getPos().offset(AttachedLogisiticalBlock.getBlockFacing(blockState));
}
@Override
@ -100,17 +120,4 @@ public class ExtractorTileEntity extends SyncedTileEntity implements IExtractor,
this.inventory = inventory;
}
@Override
public void setFilter(ItemStack stack) {
filter = stack.copy();
markDirty();
sendData();
neighborChanged();
}
@Override
public ItemStack getFilter() {
return filter.copy();
}
}

View file

@ -0,0 +1,80 @@
package com.simibubi.create.modules.logistics.block.extractor;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.logistics.block.belts.AttachedLogisiticalBlock;
import net.minecraft.block.BlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockReader;
public class LinkedExtractorBlock extends ExtractorBlock {
@Override
public BlockRenderLayer getRenderLayer() {
return BlockRenderLayer.CUTOUT_MIPPED;
}
@Override
protected BlockState getVerticalDefaultState() {
return AllBlocks.VERTICAL_LINKED_EXTRACTOR.get().getDefaultState();
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new LinkedExtractorTileEntity();
}
@Override
protected boolean reactsToRedstone() {
return false;
}
public static Pair<Vec3d, Vec3d> getFrequencySlotPosition(BlockState state) {
float verticalOffset = (state.getBlock() instanceof ExtractorBlock) ? 4f : 6f;
Vec3d first = VecHelper.voxelSpace(11.5f, verticalOffset, 14f);
Vec3d second = VecHelper.voxelSpace(11.5f, 4f + verticalOffset, 14f);
Vec3d firstUpward = VecHelper.voxelSpace(10f, 14f, 11.5f);
Vec3d secondUpward = VecHelper.voxelSpace(6f, 14f, 11.5f);
Vec3d firstDownward = VecHelper.voxelSpace(10f, 2f, 11.5f);
Vec3d secondDownward = VecHelper.voxelSpace(6f, 2f, 11.5f);
float yRot = AngleHelper.horizontalAngle(state.get(ExtractorBlock.HORIZONTAL_FACING));
if (AttachedLogisiticalBlock.isVertical(state)) {
Boolean up = state.get(AttachedLogisiticalBlock.UPWARD);
first = up ? firstUpward : firstDownward;
second = up ? secondUpward : secondDownward;
}
first = VecHelper.rotateCentered(first, yRot, Axis.Y);
second = VecHelper.rotateCentered(second, yRot, Axis.Y);
return Pair.of(first, second);
}
public static Vec3d getFrequencySlotOrientation(BlockState state) {
boolean vertical = AttachedLogisiticalBlock.isVertical(state);
float horizontalAngle = AngleHelper.horizontalAngle(state.get(ExtractorBlock.HORIZONTAL_FACING));
float xRot = vertical ? (state.get(UPWARD) ? 90 : 270) : 0;
float yRot = vertical ? horizontalAngle + 180 : horizontalAngle + 270;
float zRot = vertical ? 0 : 0;
return new Vec3d(xRot, yRot, zRot);
}
public static class Vertical extends LinkedExtractorBlock {
@Override
protected boolean isVertical() {
return true;
}
}
}

View file

@ -0,0 +1,70 @@
package com.simibubi.create.modules.logistics.block.extractor;
import static net.minecraft.state.properties.BlockStateProperties.POWERED;
import java.util.List;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour.SlotPositioning;
import com.simibubi.create.modules.logistics.block.belts.AttachedLogisiticalBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
public class LinkedExtractorTileEntity extends ExtractorTileEntity {
private static LinkBehaviour.SlotPositioning slots;
public boolean receivedSignal;
public LinkBehaviour receiver;
public LinkedExtractorTileEntity() {
super(AllTileEntities.LINKED_EXTRACTOR.type);
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
if (slots == null)
slots = new SlotPositioning(LinkedExtractorBlock::getFrequencySlotPosition,
LinkedExtractorBlock::getFrequencySlotOrientation).scale(.4f);
receiver = LinkBehaviour.receiver(this, this::setSignal).withSlotPositioning(slots);
behaviours.add(receiver);
super.addBehaviours(behaviours);
}
public void setSignal(boolean powered) {
receivedSignal = powered;
}
@Override
public void initialize() {
super.initialize();
if (world.isBlockPowered(pos))
setState(State.LOCKED);
neighborChanged();
}
@Override
public void tick() {
super.tick();
if (world.isRemote)
return;
if (receivedSignal != getBlockState().get(POWERED)) {
setLocked(receivedSignal);
world.setBlockState(pos, getBlockState().cycle(POWERED));
return;
}
}
@Override
public BlockPos getInventoryPos() {
BlockState blockState = getBlockState();
Block block = blockState.getBlock();
if (!(block instanceof ExtractorBlock))
return null;
return getPos().offset(AttachedLogisiticalBlock.getBlockFacing(blockState));
}
}

View file

@ -0,0 +1,39 @@
package com.simibubi.create.modules.logistics.block.transposer;
import com.simibubi.create.AllBlocks;
import net.minecraft.block.BlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.world.IBlockReader;
public class LinkedTransposerBlock extends TransposerBlock {
@Override
public BlockRenderLayer getRenderLayer() {
return BlockRenderLayer.CUTOUT;
}
@Override
protected BlockState getVerticalDefaultState() {
return AllBlocks.VERTICAL_LINKED_TRANSPOSER.get().getDefaultState();
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new LinkedTransposerTileEntity();
}
@Override
protected boolean reactsToRedstone() {
return false;
}
public static class Vertical extends LinkedTransposerBlock {
@Override
protected boolean isVertical() {
return true;
}
}
}

View file

@ -0,0 +1,48 @@
package com.simibubi.create.modules.logistics.block.transposer;
import static net.minecraft.state.properties.BlockStateProperties.POWERED;
import java.util.List;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour.SlotPositioning;
import com.simibubi.create.modules.logistics.block.extractor.LinkedExtractorBlock;
public class LinkedTransposerTileEntity extends TransposerTileEntity {
private static LinkBehaviour.SlotPositioning slots;
public boolean receivedSignal;
public LinkBehaviour receiver;
public LinkedTransposerTileEntity() {
super(AllTileEntities.LINKED_TRANSPOSER.type);
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
if (slots == null)
slots = new SlotPositioning(LinkedExtractorBlock::getFrequencySlotPosition,
LinkedExtractorBlock::getFrequencySlotOrientation).scale(.4f);
receiver = LinkBehaviour.receiver(this, this::setSignal).withSlotPositioning(slots);
behaviours.add(receiver);
super.addBehaviours(behaviours);
}
public void setSignal(boolean powered) {
receivedSignal = powered;
}
@Override
public void tick() {
super.tick();
if (world.isRemote)
return;
if (receivedSignal != getBlockState().get(POWERED)) {
world.setBlockState(pos, getBlockState().cycle(POWERED));
return;
}
}
}

View file

@ -0,0 +1,99 @@
package com.simibubi.create.modules.logistics.block.transposer;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.logistics.block.belts.AttachedLogisiticalBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
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;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
public class TransposerBlock extends AttachedLogisiticalBlock {
public static BooleanProperty POWERED = BlockStateProperties.POWERED;
public TransposerBlock() {
setDefaultState(getDefaultState().with(POWERED, false));
}
@Override
public boolean hasTileEntity(BlockState state) {
return true;
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new TransposerTileEntity();
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
super.fillStateContainer(builder.add(POWERED));
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return AllShapes.TRANSPOSER.get(getBlockFacing(state));
}
@Override
protected boolean isVertical() {
return false;
}
@Override
protected BlockState getVerticalDefaultState() {
return AllBlocks.VERTICAL_TRANSPOSER.getDefault();
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState stateForPlacement = super.getStateForPlacement(context);
return stateForPlacement.with(POWERED, Boolean.valueOf(context.getWorld().isBlockPowered(context.getPos())));
}
@Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
super.neighborChanged(state, worldIn, pos, blockIn, fromPos, isMoving);
if (worldIn.isRemote)
return;
if (!reactsToRedstone())
return;
boolean previouslyPowered = state.get(POWERED);
if (previouslyPowered != worldIn.isBlockPowered(pos)) {
worldIn.setBlockState(pos, state.cycle(POWERED), 2);
}
}
@Override
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
Direction back = getBlockFacing(state).getOpposite();
return super.isValidPosition(state, worldIn, pos) || canAttachToSide(worldIn, pos, back);
}
protected boolean reactsToRedstone() {
return true;
}
public static class Vertical extends TransposerBlock {
@Override
protected boolean isVertical() {
return true;
}
}
}

View file

@ -0,0 +1,41 @@
package com.simibubi.create.modules.logistics.block.transposer;
import java.util.List;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.SlotPositioning;
import com.simibubi.create.modules.logistics.block.extractor.ExtractorBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntityType;
public class TransposerTileEntity extends SmartTileEntity {
private static FilteringBehaviour.SlotPositioning slots;
private FilteringBehaviour filtering;
public TransposerTileEntity() {
this(AllTileEntities.TRANSPOSER.type);
}
protected TransposerTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
if (slots == null)
slots = new SlotPositioning(ExtractorBlock::getFilterSlotPosition, ExtractorBlock::getFilterSlotOrientation)
.scale(.4f);
filtering = new FilteringBehaviour(this).withCallback(this::filterChanged).withSlotPositioning(slots)
.showCount();
behaviours.add(filtering);
}
public void filterChanged(ItemStack stack) {
}
}

View file

@ -126,7 +126,6 @@ public class LogisticalCasingBlock extends Block implements IWithTileEntity<Logi
facing = facing.getOpposite();
return AllShapes.LOGISTICAL_CASING_CAP.get(facing);
//return state.get(PART) == Part.NONE ? VoxelShapers.LOGISTICAL_CASING_SINGLE_SHAPE : VoxelShapes.fullCube();
}
@Override

View file

@ -0,0 +1,127 @@
package com.simibubi.create.modules.logistics.management.base;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.VoxelShaper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.EnumProperty;
import net.minecraft.state.IProperty;
import net.minecraft.state.StateContainer.Builder;
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.IStringSerializable;
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;
import net.minecraft.world.IWorld;
public class NewLogisticalCasingBlock extends Block {
public static final EnumProperty<Direction.Axis> AXIS = BlockStateProperties.AXIS;
public static final IProperty<Part> PART = EnumProperty.create("part", Part.class);
public static final BooleanProperty ACTIVE = BooleanProperty.create("active");
public NewLogisticalCasingBlock() {
super(Properties.from(Blocks.DARK_OAK_PLANKS));
setDefaultState(getDefaultState().with(PART, Part.NONE).with(AXIS, Axis.Y).with(ACTIVE, false));
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState state = getDefaultState();
for (Direction face : Direction.values()) {
BlockState neighbour = context.getWorld().getBlockState(context.getPos().offset(face));
if (!AllBlocks.LOGISTICAL_CASING.typeOf(neighbour))
continue;
if (neighbour.get(PART) != Part.NONE && face.getAxis() != neighbour.get(AXIS))
continue;
state = state.with(PART, face.getAxisDirection() == AxisDirection.POSITIVE ? Part.START : Part.END);
state = state.with(AXIS, face.getAxis());
}
return state;
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
Part part = state.get(PART);
if (part == Part.NONE)
return AllShapes.LOGISTICAL_CASING_SINGLE_SHAPE;
if (part == Part.MIDDLE)
return AllShapes.LOGISTICAL_CASING_MIDDLE.get(state.get(AXIS));
Direction facing = VoxelShaper.axisAsFace(state.get(AXIS));
if (part == Part.END)
facing = facing.getOpposite();
return AllShapes.LOGISTICAL_CASING_CAP.get(facing);
}
@Override
public BlockState updatePostPlacement(BlockState state, Direction face, BlockState facingState, IWorld worldIn,
BlockPos currentPos, BlockPos facingPos) {
Part part = state.get(PART);
boolean neighbourPresent = AllBlocks.LOGISTICAL_CASING.typeOf(facingState);
boolean alongAxis = face.getAxis() == state.get(AXIS);
boolean positive = face.getAxisDirection() == AxisDirection.POSITIVE;
boolean neighbourAlongAxis = neighbourPresent
&& (facingState.get(PART) == Part.NONE || facingState.get(AXIS) == face.getAxis());
if (part == Part.NONE && neighbourPresent && neighbourAlongAxis) {
state = state.with(PART, positive ? Part.START : Part.END);
return state.with(AXIS, face.getAxis());
}
if (!alongAxis)
return state;
if (part == Part.END) {
if (positive && neighbourPresent && neighbourAlongAxis)
return state.with(PART, Part.MIDDLE);
if (!positive && !neighbourPresent)
return state.with(PART, Part.NONE).with(AXIS, Axis.Y);
}
if (part == Part.START) {
if (!positive && neighbourPresent && neighbourAlongAxis)
return state.with(PART, Part.MIDDLE);
if (positive && !neighbourPresent)
return state.with(PART, Part.NONE).with(AXIS, Axis.Y);
}
if (part == Part.MIDDLE) {
if (!positive && !neighbourPresent)
return state.with(PART, Part.START);
if (positive && !neighbourPresent)
return state.with(PART, Part.END);
}
return state;
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(AXIS, PART, ACTIVE);
super.fillStateContainer(builder);
}
public enum Part implements IStringSerializable {
START, MIDDLE, END, NONE;
@Override
public String getName() {
return name().toLowerCase();
}
}
}

View file

@ -1,9 +1,10 @@
{
"forge_marker": 1,
"defaults": {
"model": "create:block/belt_funnel"
},
"variants": {
"belt": {
"true": { "model": "create:block/funnel/horizontal_belt" },
"false": { "model": "create:block/funnel/horizontal" }
},
"facing": {
"south": { "y": 180 },
"east": { "y": 90 },

View file

@ -1,17 +1,17 @@
{
"variants": {
"powered=false,facing=up": { "model": "create:block/contact" },
"powered=false,facing=down": { "model": "create:block/contact", "x": 180 },
"powered=false,facing=north": { "model": "create:block/contact", "x": 90 },
"powered=false,facing=south": { "model": "create:block/contact", "x": 90, "y": 180 },
"powered=false,facing=east": { "model": "create:block/contact", "x": 90, "y": 90 },
"powered=false,facing=west": { "model": "create:block/contact", "x": 90, "y": 270 },
"powered=true,facing=up": { "model": "create:block/contact_powered" },
"powered=true,facing=down": { "model": "create:block/contact_powered", "x": 180 },
"powered=true,facing=north": { "model": "create:block/contact_powered", "x": 90 },
"powered=true,facing=south": { "model": "create:block/contact_powered", "x": 90, "y": 180 },
"powered=true,facing=east": { "model": "create:block/contact_powered", "x": 90, "y": 90 },
"powered=true,facing=west": { "model": "create:block/contact_powered", "x": 90, "y": 270 }
}
"forge_marker": 1,
"variants": {
"powered": {
"true": { "model": "create:block/contact_powered" },
"false": { "model": "create:block/contact" }
},
"facing": {
"north": { "x": 90 },
"south": { "x": 90, "y": 180 },
"west": { "x": 90, "y": 270 },
"up": { },
"down": { "x": 180 },
"east": { "x": 90, "y": 90 }
}
}
}

View file

@ -0,0 +1,15 @@
{
"forge_marker": 1,
"variants": {
"powered": {
"true": { "model": "create:block/transposer/linked_powered" },
"false": { "model": "create:block/transposer/linked" }
},
"facing": {
"north": { "y": 0 },
"south": { "y": 180 },
"west": { "y": 270 },
"east": { "y": 90 }
}
}
}

View file

@ -0,0 +1,15 @@
{
"forge_marker": 1,
"variants": {
"powered": {
"true": { "model": "create:block/transposer/default_powered" },
"false": { "model": "create:block/transposer/default" }
},
"facing": {
"north": { "y": 0 },
"south": { "y": 180 },
"west": { "y": 270 },
"east": { "y": 90 }
}
}
}

View file

@ -0,0 +1,16 @@
{
"forge_marker": 1,
"defaults": {
"model": "create:block/funnel/vertical"
},
"variants": {
"upward=true,facing=south": { "y": 180, "x": 270 },
"upward=true,facing=east": { "y": 90, "x": 270 },
"upward=true,facing=north": { "y": 0, "x": 270 },
"upward=true,facing=west": { "y": 270, "x": 270 },
"upward=false,facing=south": { "y": 0, "x": 90 },
"upward=false,facing=east": { "y": 270, "x": 90 },
"upward=false,facing=north": { "y": 180, "x": 90 },
"upward=false,facing=west": { "y": 90, "x": 90 }
}
}

View file

@ -0,0 +1,27 @@
{
"forge_marker": 1,
"defaults": {
"model": "create:block/transposer/vertical_linked"
},
"variants": {
"powered=true,upward=true,facing=south": { "model": "create:block/transposer/vertical_linked_powered", "y": 180, "x": 270 },
"powered=true,upward=true,facing=east": { "model": "create:block/transposer/vertical_linked_powered", "y": 90, "x": 270 },
"powered=true,upward=true,facing=north": { "model": "create:block/transposer/vertical_linked_powered", "y": 0, "x": 270 },
"powered=true,upward=true,facing=west": { "model": "create:block/transposer/vertical_linked_powered", "y": 270, "x": 270 },
"powered=true,upward=false,facing=south": { "model": "create:block/transposer/vertical_linked_powered", "y": 0, "x": 90 },
"powered=true,upward=false,facing=east": { "model": "create:block/transposer/vertical_linked_powered", "y": 270, "x": 90 },
"powered=true,upward=false,facing=north": { "model": "create:block/transposer/vertical_linked_powered", "y": 180, "x": 90 },
"powered=true,upward=false,facing=west": { "model": "create:block/transposer/vertical_linked_powered", "y": 90, "x": 90 },
"powered=false,upward=true,facing=south": { "y": 180, "x": 270 },
"powered=false,upward=true,facing=east": { "y": 90, "x": 270 },
"powered=false,upward=true,facing=north": { "y": 0, "x": 270 },
"powered=false,upward=true,facing=west": { "y": 270, "x": 270 },
"powered=false,upward=false,facing=south": { "y": 0, "x": 90 },
"powered=false,upward=false,facing=east": { "y": 270, "x": 90 },
"powered=false,upward=false,facing=north": { "y": 180, "x": 90 },
"powered=false,upward=false,facing=west": { "y": 90, "x": 90 }
}
}

View file

@ -0,0 +1,27 @@
{
"forge_marker": 1,
"defaults": {
"model": "create:block/transposer/default"
},
"variants": {
"powered=true,upward=true,facing=south": { "model": "create:block/transposer/default_powered", "y": 180, "x": 270 },
"powered=true,upward=true,facing=east": { "model": "create:block/transposer/default_powered", "y": 90, "x": 270 },
"powered=true,upward=true,facing=north": { "model": "create:block/transposer/default_powered", "y": 0, "x": 270 },
"powered=true,upward=true,facing=west": { "model": "create:block/transposer/default_powered", "y": 270, "x": 270 },
"powered=true,upward=false,facing=south": { "model": "create:block/transposer/default_powered", "y": 0, "x": 90 },
"powered=true,upward=false,facing=east": { "model": "create:block/transposer/default_powered", "y": 270, "x": 90 },
"powered=true,upward=false,facing=north": { "model": "create:block/transposer/default_powered", "y": 180, "x": 90 },
"powered=true,upward=false,facing=west": { "model": "create:block/transposer/default_powered", "y": 90, "x": 90 },
"powered=false,upward=true,facing=south": { "y": 180, "x": 270 },
"powered=false,upward=true,facing=east": { "y": 90, "x": 270 },
"powered=false,upward=true,facing=north": { "y": 0, "x": 270 },
"powered=false,upward=true,facing=west": { "y": 270, "x": 270 },
"powered=false,upward=false,facing=south": { "y": 0, "x": 90 },
"powered=false,upward=false,facing=east": { "y": 270, "x": 90 },
"powered=false,upward=false,facing=north": { "y": 180, "x": 90 },
"powered=false,upward=false,facing=west": { "y": 90, "x": 90 }
}
}

View file

@ -99,8 +99,10 @@
"block.create.stockswitch": "Stockpile Switch",
"block.create.flexcrate": "FlexCrate",
"block.create.extractor": "Extractor",
"block.create.belt_funnel": "Belt Funnel",
"block.create.belt_funnel": "Funnel",
"block.create.linked_extractor": "Linked Extractor",
"block.create.transposer": "Transposer",
"block.create.linked_transposer": "Linked Transposer",
"block.create.pulse_repeater": "Pulse Repeater",
"block.create.flexpeater": "FlexPeater",
"block.create.entity_detector": "Belt Observer",

View file

@ -1,92 +1,116 @@
{
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"brass_casing": "create:block/brass_casing",
"textures": {
"brass_casing": "create:block/brass_casing",
"extractor": "create:block/extractor",
"entity_detector_off": "create:block/entity_detector_off",
"entity_detector_front": "create:block/entity_detector_front",
"particle": "create:block/entity_detector_off"
},
"elements": [
{
"name": "Bottom",
"from": [ 0, 0, 0 ],
"to": [ 16, 2, 16 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 0, 14, 16, 16 ] },
"east": { "texture": "#entity_detector_off", "uv": [ 0, 0, 2, 16 ], "rotation": 270 },
"south": { "texture": "#brass_casing", "uv": [ 0, 14, 16, 16 ] },
"west": { "texture": "#entity_detector_off", "uv": [ 14, 0, 16, 16 ], "rotation": 90 },
"up": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 16 ] },
"down": { "texture": "#entity_detector_off", "uv": [ 0, 0, 16, 16 ] }
}
},
{
"name": "Top",
"from": [ 0, 14, 0 ],
"to": [ 16, 16, 16 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 2 ] },
"east": { "texture": "#entity_detector_off", "uv": [ 14, 0, 16, 16 ], "rotation": 270 },
"south": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 2 ] },
"west": { "texture": "#entity_detector_off", "uv": [ 0, 0, 2, 16 ], "rotation": 90 },
"up": { "texture": "#entity_detector_off", "uv": [ 0, 0, 16, 16 ], "rotation": 180 },
"down": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 16 ] }
}
},
{
"name": "Side",
"from": [ 0, 2, 0 ],
"to": [ 2, 14, 16 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 14, 2, 16, 14 ] },
"east": { "texture": "#brass_casing", "uv": [ 2, 0, 14, 16 ], "rotation": 90 },
"south": { "texture": "#brass_casing", "uv": [ 0, 2, 2, 14 ] },
"west": { "texture": "#entity_detector_off", "uv": [ 2, 0, 14, 16 ], "rotation": 90 },
"up": { "texture": "#entity_detector_off", "uv": [ 0, 0, 2, 16 ] },
"down": { "texture": "#entity_detector_off", "uv": [ 0, 0, 2, 16 ] }
}
},
{
"name": "Side",
"from": [ 14, 2, 0 ],
"to": [ 16, 14, 16 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 0, 2, 2, 14 ] },
"east": { "texture": "#entity_detector_off", "uv": [ 2, 0, 14, 16 ], "rotation": 270 },
"south": { "texture": "#brass_casing", "uv": [ 14, 2, 16, 14 ] },
"west": { "texture": "#brass_casing", "uv": [ 2, 0, 14, 16 ], "rotation": 90 },
"up": { "texture": "#entity_detector_off", "uv": [ 0, 0, 2, 16 ] },
"down": { "texture": "#entity_detector_off", "uv": [ 0, 0, 2, 16 ] }
}
},
{
"name": "Center",
"from": [ 2, 2, 1 ],
"to": [ 14, 14, 17 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 2, 2, 14, 14 ] },
"east": { "texture": "#entity_detector_front", "uv": [ 0, 2, 16, 14 ] },
"south": { "texture": "#entity_detector_front", "uv": [ 2, 2, 14, 14 ] },
"west": { "texture": "#entity_detector_front", "uv": [ 0, 2, 16, 14 ] },
"up": { "texture": "#brass_casing", "uv": [ 0, 0, 12, 16 ] },
"down": { "texture": "#brass_casing", "uv": [ 0, 0, 12, 16 ] }
}
},
{
"name": "Filter",
"from": [ 5, 14, 15 ],
"to": [ 11, 16, 20 ],
"rotation": { "origin": [ 9, 16, 16 ], "axis": "x", "angle": 22.5 },
"faces": {
"north": { "texture": "#entity_detector_off", "uv": [ 5, 14, 11, 16 ] },
"east": { "texture": "#entity_detector_off", "uv": [ 1, 4, 6, 6 ], "rotation": 180 },
"south": { "texture": "#entity_detector_off", "uv": [ 5, 4, 11, 6 ], "rotation": 180 },
"west": { "texture": "#entity_detector_off", "uv": [ 10, 4, 15, 6 ], "rotation": 180 },
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 },
"down": { "texture": "#entity_detector_off", "uv": [ 5, 5, 11, 10 ] }
}
}
]
"particle": "create:block/entity_detector_off",
"entity_detector_off": "create:block/entity_detector_off",
"entity_detector_front": "create:block/entity_detector_front"
},
"elements": [
{
"name": "Bottom",
"from": [0, 0, 0],
"to": [16, 2, 16],
"faces": {
"north": {"uv": [0, 14, 16, 16], "texture": "#brass_casing"},
"east": {"uv": [0, 0, 2, 16], "rotation": 270, "texture": "#entity_detector_off"},
"south": {"uv": [0, 14, 16, 16], "texture": "#brass_casing"},
"west": {"uv": [14, 0, 16, 16], "rotation": 90, "texture": "#entity_detector_off"},
"up": {"uv": [0, 0, 16, 16], "texture": "#brass_casing"},
"down": {"uv": [0, 0, 16, 16], "texture": "#entity_detector_off"}
}
},
{
"name": "Top",
"from": [0, 14, 0],
"to": [5, 16, 16],
"faces": {
"north": {"uv": [11, 0, 16, 2], "texture": "#brass_casing"},
"east": {"uv": [14, 0, 16, 16], "rotation": 270, "texture": "#entity_detector_off"},
"south": {"uv": [0, 0, 5, 2], "texture": "#brass_casing"},
"west": {"uv": [0, 0, 2, 16], "rotation": 90, "texture": "#entity_detector_off"},
"up": {"uv": [11, 0, 16, 16], "rotation": 180, "texture": "#entity_detector_off"},
"down": {"uv": [0, 0, 5, 16], "texture": "#brass_casing"}
}
},
{
"name": "Top",
"from": [11, 14, 0],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [0, 0, 5, 2], "texture": "#brass_casing"},
"east": {"uv": [14, 0, 16, 16], "rotation": 270, "texture": "#entity_detector_off"},
"south": {"uv": [11, 0, 16, 2], "texture": "#brass_casing"},
"west": {"uv": [0, 0, 2, 16], "rotation": 90, "texture": "#entity_detector_off"},
"up": {"uv": [0, 0, 5, 16], "rotation": 180, "texture": "#entity_detector_off"},
"down": {"uv": [0, 0, 5, 16], "texture": "#brass_casing"}
}
},
{
"name": "Top",
"from": [5, 14, 0],
"to": [11, 16, 14],
"faces": {
"north": {"uv": [5, 0, 11, 2], "texture": "#brass_casing"},
"east": {"uv": [14, 0, 16, 14], "rotation": 270, "texture": "#entity_detector_off"},
"south": {"uv": [5, 1, 11, 3], "rotation": 180, "texture": "#entity_detector_off"},
"west": {"uv": [0, 0, 2, 14], "rotation": 90, "texture": "#entity_detector_off"},
"up": {"uv": [5, 2, 11, 16], "rotation": 180, "texture": "#entity_detector_off"},
"down": {"uv": [5, 2, 11, 16], "texture": "#brass_casing"}
}
},
{
"name": "Side",
"from": [0, 2, 0],
"to": [2, 14, 16],
"faces": {
"north": {"uv": [14, 2, 16, 14], "texture": "#brass_casing"},
"east": {"uv": [2, 0, 14, 16], "rotation": 90, "texture": "#brass_casing"},
"south": {"uv": [0, 2, 2, 14], "texture": "#brass_casing"},
"west": {"uv": [2, 0, 14, 16], "rotation": 90, "texture": "#entity_detector_off"},
"down": {"uv": [0, 0, 2, 16], "texture": "#entity_detector_off"}
}
},
{
"name": "Side",
"from": [14, 2, 0],
"to": [16, 14, 16],
"faces": {
"north": {"uv": [0, 2, 2, 14], "texture": "#brass_casing"},
"east": {"uv": [2, 0, 14, 16], "rotation": 270, "texture": "#entity_detector_off"},
"south": {"uv": [14, 2, 16, 14], "texture": "#brass_casing"},
"west": {"uv": [2, 0, 14, 16], "rotation": 90, "texture": "#brass_casing"},
"down": {"uv": [0, 0, 2, 16], "texture": "#entity_detector_off"}
}
},
{
"name": "Center",
"from": [2, 2, 1],
"to": [14, 14, 17],
"faces": {
"north": {"uv": [2, 2, 14, 14], "texture": "#brass_casing"},
"east": {"uv": [0, 2, 16, 14], "texture": "#entity_detector_front"},
"south": {"uv": [2, 2, 14, 14], "texture": "#entity_detector_front"},
"west": {"uv": [0, 2, 16, 14], "texture": "#entity_detector_front"},
"up": {"uv": [0, 0, 12, 16], "texture": "#brass_casing"},
"down": {"uv": [0, 0, 12, 16], "texture": "#brass_casing"}
}
},
{
"name": "Filter",
"from": [5, 13, 13],
"to": [11, 15, 18],
"rotation": {"angle": 0, "axis": "x", "origin": [9, 15, 16]},
"faces": {
"north": {"uv": [4, 1, 6, 7], "rotation": 270, "texture": "#extractor"},
"east": {"uv": [4, 2, 6, 7], "rotation": 270, "texture": "#extractor"},
"south": {"uv": [4, 1, 6, 7], "rotation": 270, "texture": "#extractor"},
"west": {"uv": [4, 2, 6, 7], "rotation": 270, "texture": "#extractor"},
"up": {"uv": [0, 9, 5, 15], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [5, 5, 11, 10], "texture": "#entity_detector_off"}
}
}
]
}

View file

@ -1,105 +1,131 @@
{
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"brass_casing": "create:block/brass_casing",
"extractor": "create:block/extractor",
"entity_detector_off": "create:block/entity_detector_off",
"entity_detector_front": "create:block/entity_detector_front",
"particle": "create:block/entity_detector_off"
},
"elements": [
{
"name": "Bottom",
"from": [ 0, 0, 0 ],
"to": [ 16, 2, 16 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 0, 14, 16, 16 ] },
"east": { "texture": "#entity_detector_off", "uv": [ 0, 0, 2, 16 ], "rotation": 270 },
"south": { "texture": "#brass_casing", "uv": [ 0, 14, 16, 16 ] },
"west": { "texture": "#entity_detector_off", "uv": [ 14, 0, 16, 16 ], "rotation": 90 },
"up": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 16 ] },
"down": { "texture": "#entity_detector_off", "uv": [ 0, 0, 16, 16 ] }
}
},
{
"name": "Top",
"from": [ 0, 14, 0 ],
"to": [ 16, 16, 16 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 2 ] },
"east": { "texture": "#entity_detector_off", "uv": [ 14, 0, 16, 16 ], "rotation": 270 },
"south": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 2 ] },
"west": { "texture": "#entity_detector_off", "uv": [ 0, 0, 2, 16 ], "rotation": 90 },
"up": { "texture": "#entity_detector_off", "uv": [ 0, 0, 16, 16 ], "rotation": 180 },
"down": { "texture": "#brass_casing", "uv": [ 0, 0, 16, 16 ] }
}
},
{
"name": "Side",
"from": [ 0, 2, 0 ],
"to": [ 2, 14, 16 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 14, 2, 16, 14 ] },
"east": { "texture": "#brass_casing", "uv": [ 2, 0, 14, 16 ], "rotation": 90 },
"south": { "texture": "#brass_casing", "uv": [ 0, 2, 2, 14 ] },
"west": { "texture": "#entity_detector_off", "uv": [ 2, 0, 14, 16 ], "rotation": 90 },
"up": { "texture": "#entity_detector_off", "uv": [ 0, 0, 2, 16 ] },
"down": { "texture": "#entity_detector_off", "uv": [ 0, 0, 2, 16 ] }
}
},
{
"name": "Side",
"from": [ 14, 2, 0 ],
"to": [ 16, 14, 16 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 0, 2, 2, 14 ] },
"east": { "texture": "#entity_detector_off", "uv": [ 2, 0, 14, 16 ], "rotation": 270 },
"south": { "texture": "#brass_casing", "uv": [ 14, 2, 16, 14 ] },
"west": { "texture": "#brass_casing", "uv": [ 2, 0, 14, 16 ], "rotation": 90 },
"up": { "texture": "#entity_detector_off", "uv": [ 0, 0, 2, 16 ] },
"down": { "texture": "#entity_detector_off", "uv": [ 0, 0, 2, 16 ] }
}
},
{
"name": "Center",
"from": [ 2, 2, 1 ],
"to": [ 14, 14, 17 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 2, 2, 14, 14 ] },
"east": { "texture": "#entity_detector_front", "uv": [ 0, 2, 16, 14 ] },
"south": { "texture": "#entity_detector_front", "uv": [ 2, 2, 14, 14 ] },
"west": { "texture": "#entity_detector_front", "uv": [ 0, 2, 16, 14 ] },
"up": { "texture": "#brass_casing", "uv": [ 0, 0, 12, 16 ] },
"down": { "texture": "#brass_casing", "uv": [ 0, 0, 12, 16 ] }
}
},
{
"name": "Belt Thing",
"from": [ 1, 5, 16 ],
"to": [ 15, 11, 30 ],
"faces": {
"north": { "texture": "#entity_detector_off", "uv": [ 1, 0, 15, 6 ] },
"east": { "texture": "#entity_detector_off", "uv": [ 1, 0, 15, 6 ] },
"south": { "texture": "#entity_detector_off", "uv": [ 1, 0, 15, 6 ] },
"west": { "texture": "#entity_detector_off", "uv": [ 2, 0, 16, 6 ] },
"up": { "texture": "#brass_casing", "uv": [ 1, 1, 15, 15 ] },
"down": { "texture": "#brass_casing", "uv": [ 1, 1, 15, 15 ] }
}
},
{
"name": "Filter",
"from": [ 5, 14, 15 ],
"to": [ 11, 16, 20 ],
"rotation": { "origin": [ 9, 16, 16 ], "axis": "x", "angle": 22.5 },
"faces": {
"north": { "texture": "#entity_detector_off", "uv": [ 5, 14, 11, 16 ] },
"east": { "texture": "#entity_detector_off", "uv": [ 1, 4, 6, 6 ], "rotation": 180 },
"south": { "texture": "#entity_detector_off", "uv": [ 5, 4, 11, 6 ], "rotation": 180 },
"west": { "texture": "#entity_detector_off", "uv": [ 10, 4, 15, 6 ], "rotation": 180 },
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 },
"down": { "texture": "#entity_detector_off", "uv": [ 5, 5, 11, 10 ] }
}
}
]
"textures": {
"3": "create:block/extractor",
"brass_casing": "create:block/brass_casing",
"particle": "create:block/entity_detector_off",
"entity_detector_off": "create:block/entity_detector_off",
"entity_detector_front": "create:block/entity_detector_front"
},
"elements": [
{
"name": "Bottom",
"from": [0, 0, 0],
"to": [16, 2, 16],
"faces": {
"north": {"uv": [0, 14, 16, 16], "texture": "#brass_casing"},
"east": {"uv": [0, 0, 2, 16], "rotation": 270, "texture": "#entity_detector_off"},
"south": {"uv": [0, 14, 16, 16], "texture": "#brass_casing"},
"west": {"uv": [14, 0, 16, 16], "rotation": 90, "texture": "#entity_detector_off"},
"up": {"uv": [0, 0, 16, 16], "texture": "#brass_casing"},
"down": {"uv": [0, 0, 16, 16], "texture": "#entity_detector_off"}
}
},
{
"name": "Side",
"from": [0, 2, 0],
"to": [2, 14, 16],
"faces": {
"north": {"uv": [14, 2, 16, 14], "texture": "#brass_casing"},
"east": {"uv": [2, 0, 14, 16], "rotation": 90, "texture": "#brass_casing"},
"south": {"uv": [0, 2, 2, 14], "texture": "#brass_casing"},
"west": {"uv": [2, 0, 14, 16], "rotation": 90, "texture": "#entity_detector_off"},
"up": {"uv": [0, 0, 2, 16], "texture": "#entity_detector_off"},
"down": {"uv": [0, 0, 2, 16], "texture": "#entity_detector_off"}
}
},
{
"name": "Side",
"from": [14, 2, 0],
"to": [16, 14, 16],
"faces": {
"north": {"uv": [0, 2, 2, 14], "texture": "#brass_casing"},
"east": {"uv": [2, 0, 14, 16], "rotation": 270, "texture": "#entity_detector_off"},
"south": {"uv": [14, 2, 16, 14], "texture": "#brass_casing"},
"west": {"uv": [2, 0, 14, 16], "rotation": 90, "texture": "#brass_casing"},
"up": {"uv": [0, 0, 2, 16], "texture": "#entity_detector_off"},
"down": {"uv": [0, 0, 2, 16], "texture": "#entity_detector_off"}
}
},
{
"name": "Center",
"from": [2, 2, 1],
"to": [14, 14, 17],
"faces": {
"north": {"uv": [2, 2, 14, 14], "texture": "#brass_casing"},
"east": {"uv": [0, 2, 16, 14], "texture": "#entity_detector_front"},
"south": {"uv": [2, 2, 14, 14], "texture": "#entity_detector_front"},
"west": {"uv": [0, 2, 16, 14], "texture": "#entity_detector_front"},
"up": {"uv": [0, 0, 12, 16], "texture": "#brass_casing"},
"down": {"uv": [0, 0, 12, 16], "texture": "#brass_casing"}
}
},
{
"name": "Belt Thing",
"from": [1, 5, 16],
"to": [15, 11, 30],
"faces": {
"north": {"uv": [1, 0, 15, 6], "texture": "#entity_detector_off"},
"east": {"uv": [1, 0, 15, 6], "texture": "#entity_detector_off"},
"south": {"uv": [1, 0, 15, 6], "texture": "#entity_detector_off"},
"west": {"uv": [2, 0, 16, 6], "texture": "#entity_detector_off"},
"up": {"uv": [1, 1, 15, 15], "texture": "#brass_casing"},
"down": {"uv": [1, 1, 15, 15], "texture": "#brass_casing"}
}
},
{
"name": "Top",
"from": [0, 14, 0],
"to": [5, 16, 16],
"faces": {
"north": {"uv": [11, 0, 16, 2], "texture": "#brass_casing"},
"east": {"uv": [14, 0, 16, 16], "rotation": 270, "texture": "#entity_detector_off"},
"south": {"uv": [0, 0, 5, 2], "texture": "#brass_casing"},
"west": {"uv": [0, 0, 2, 16], "rotation": 90, "texture": "#entity_detector_off"},
"up": {"uv": [11, 0, 16, 16], "rotation": 180, "texture": "#entity_detector_off"},
"down": {"uv": [0, 0, 5, 16], "texture": "#entity_detector_off"}
}
},
{
"name": "Top",
"from": [5, 14, 0],
"to": [11, 16, 14],
"faces": {
"north": {"uv": [5, 0, 11, 2], "texture": "#brass_casing"},
"east": {"uv": [14, 0, 16, 14], "rotation": 270, "texture": "#entity_detector_off"},
"south": {"uv": [5, 1, 11, 3], "rotation": 180, "texture": "#entity_detector_off"},
"west": {"uv": [0, 0, 2, 14], "rotation": 90, "texture": "#entity_detector_off"},
"up": {"uv": [5, 2, 11, 16], "rotation": 180, "texture": "#entity_detector_off"},
"down": {"uv": [5, 2, 11, 16], "texture": "#entity_detector_off"}
}
},
{
"name": "Top",
"from": [11, 14, 0],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [0, 0, 5, 2], "texture": "#brass_casing"},
"east": {"uv": [14, 0, 16, 16], "rotation": 270, "texture": "#entity_detector_off"},
"south": {"uv": [11, 0, 16, 2], "texture": "#brass_casing"},
"west": {"uv": [0, 0, 2, 16], "rotation": 90, "texture": "#entity_detector_off"},
"up": {"uv": [0, 0, 5, 16], "rotation": 180, "texture": "#entity_detector_off"},
"down": {"uv": [0, 0, 5, 16], "texture": "#entity_detector_off"}
}
},
{
"name": "Filter",
"from": [5, 13, 13],
"to": [11, 15, 18],
"rotation": {"angle": 0, "axis": "y", "origin": [9, 15, 16]},
"faces": {
"north": {"uv": [4, 1, 6, 7], "rotation": 270, "texture": "#3"},
"east": {"uv": [4, 2, 6, 7], "rotation": 270, "texture": "#3"},
"south": {"uv": [4, 1, 6, 7], "rotation": 270, "texture": "#3"},
"west": {"uv": [4, 2, 6, 7], "rotation": 270, "texture": "#3"},
"up": {"uv": [0, 9, 5, 15], "rotation": 90, "texture": "#3"},
"down": {"uv": [5, 5, 11, 10], "texture": "#3"}
}
}
]
}

View file

@ -1,7 +1,7 @@
{
"parent": "create:block/entity_detector_with_belt",
"textures": {
"extractor": "create:block/extractor_powered",
"3": "create:block/extractor_powered",
"entity_detector_off": "create:block/entity_detector_on",
"particle": "create:block/entity_detector_on"
}

View file

@ -67,7 +67,7 @@
{
"name": "FilterSpot",
"from": [5, 10, -1],
"to": [11, 11, 4],
"to": [11, 11.05, 4],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 11, -1]},
"faces": {
"north": {"uv": [0, 9, 1, 15], "rotation": 90, "texture": "#extractor"},

View file

@ -70,7 +70,7 @@
{
"name": "FilterSpot",
"from": [5, 10, -1],
"to": [11, 11, 4],
"to": [11, 11.05, 4],
"rotation": {"angle": 0, "axis": "x", "origin": [8, 11, -1]},
"faces": {
"north": {"uv": [0, 9, 1, 15], "rotation": 90, "texture": "#extractor"},

View file

@ -60,8 +60,7 @@
"from": [5, 0, 5],
"to": [11, 4, 11],
"faces": {
"up": {"uv": [7, 1, 13, 7], "rotation": 180, "texture": "#extractor"},
"down": {"uv": [5, 5, 11, 11], "texture": "#1"}
"up": {"uv": [7, 1, 13, 7], "rotation": 180, "texture": "#extractor"}
}
},
{
@ -75,6 +74,18 @@
"up": {"uv": [4, 9, 5, 15], "rotation": 270, "texture": "#extractor"},
"down": {"uv": [0, 9, 1, 15], "rotation": 90, "texture": "#extractor"}
}
},
{
"name": "Extension",
"from": [4.9, -3, 4.9],
"to": [11.1, -1, 11.1],
"faces": {
"north": {"uv": [3, 0, 5, 6], "rotation": 270, "texture": "#extractor"},
"east": {"uv": [3, 0, 5, 6], "rotation": 270, "texture": "#extractor"},
"south": {"uv": [3, 0, 5, 6], "rotation": 270, "texture": "#extractor"},
"west": {"uv": [3, 0, 5, 6], "rotation": 270, "texture": "#extractor"},
"down": {"uv": [5, 5, 11, 11], "texture": "#1"}
}
}
],
"display": {
@ -115,7 +126,7 @@
{
"name": "vertical",
"origin": [8, 8, 8],
"children": [0, 1, 2, 3, 4, 5]
"children": [0, 1, 2, 3, 4, 5, 6]
}
]
}

View file

@ -61,8 +61,7 @@
"from": [5, 0, 5],
"to": [11, 4, 11],
"faces": {
"up": {"uv": [7, 1, 13, 7], "rotation": 180, "texture": "#extractor"},
"down": {"uv": [5, 5, 11, 11], "texture": "#1"}
"up": {"uv": [7, 1, 13, 7], "rotation": 180, "texture": "#extractor"}
}
},
{
@ -116,6 +115,18 @@
"up": {"uv": [4, 0, 9, 5], "texture": "#redstone_antenna"},
"down": {"uv": [4, 0, 9, 5], "texture": "#redstone_antenna"}
}
},
{
"name": "Extension",
"from": [4.9, -3, 4.9],
"to": [11.1, -1, 11.1],
"faces": {
"north": {"uv": [3, 0, 5, 6], "rotation": 270, "texture": "#extractor"},
"east": {"uv": [3, 0, 5, 6], "rotation": 270, "texture": "#extractor"},
"south": {"uv": [3, 0, 5, 6], "rotation": 270, "texture": "#extractor"},
"west": {"uv": [3, 0, 5, 6], "rotation": 270, "texture": "#extractor"},
"down": {"uv": [5, 5, 11, 11], "texture": "#1"}
}
}
],
"display": {
@ -156,7 +167,7 @@
{
"name": "vertical",
"origin": [8, 8, 8],
"children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
"children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}
]
}

View file

@ -0,0 +1,142 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"3": "block/dark_oak_log_top",
"4": "create:block/extractor",
"brass_casing": "create:block/brass_casing",
"belt_funnel": "create:block/belt_funnel",
"particle": "create:block/package_funnel_horizontal",
"package_funnel_horizontal": "create:block/package_funnel_horizontal"
},
"elements": [
{
"name": "Cube",
"from": [1, 1, -1],
"to": [15, 2, 3],
"faces": {
"north": {"uv": [1, 14, 15, 15], "texture": "#3"},
"east": {"uv": [0, 12, 1, 16], "rotation": 270, "texture": "#belt_funnel"},
"south": {"uv": [0, 13, 14, 14], "texture": "#package_funnel_horizontal"},
"west": {"uv": [0, 12, 1, 16], "rotation": 90, "texture": "#belt_funnel"},
"up": {"uv": [0, 12, 14, 16], "rotation": 180, "texture": "#belt_funnel"},
"down": {"uv": [0, 12, 14, 16], "texture": "#belt_funnel"}
}
},
{
"name": "Cube",
"from": [11, 14, -1],
"to": [15, 15, 3],
"faces": {
"north": {"uv": [11, 1, 15, 2], "texture": "#3"},
"east": {"uv": [13, 12, 14, 16], "rotation": 270, "texture": "#belt_funnel"},
"south": {"uv": [10, 0, 14, 1], "texture": "#package_funnel_horizontal"},
"west": {"uv": [13, 12, 14, 16], "rotation": 90, "texture": "#belt_funnel"},
"up": {"uv": [0, 12, 4, 16], "rotation": 180, "texture": "#belt_funnel"},
"down": {"uv": [0, 12, 4, 16], "texture": "#belt_funnel"}
}
},
{
"name": "Cube",
"from": [1, 14, -1],
"to": [5, 15, 3],
"faces": {
"north": {"uv": [1, 1, 5, 2], "texture": "#3"},
"east": {"uv": [13, 12, 14, 16], "rotation": 270, "texture": "#belt_funnel"},
"south": {"uv": [0, 0, 4, 1], "texture": "#package_funnel_horizontal"},
"west": {"uv": [13, 12, 14, 16], "rotation": 90, "texture": "#belt_funnel"},
"up": {"uv": [10, 12, 14, 16], "rotation": 180, "texture": "#belt_funnel"},
"down": {"uv": [0, 12, 4, 16], "texture": "#belt_funnel"}
}
},
{
"name": "Cube",
"from": [1, 2, -1],
"to": [2, 14, 3],
"faces": {
"north": {"uv": [14, 2, 15, 14], "texture": "#3"},
"east": {"uv": [1, 12, 13, 16], "rotation": 270, "texture": "#belt_funnel"},
"south": {"uv": [0, 1, 1, 13], "texture": "#package_funnel_horizontal"},
"west": {"uv": [1, 12, 13, 16], "rotation": 90, "texture": "#belt_funnel"}
}
},
{
"name": "Cube",
"from": [14, 2, -1],
"to": [15, 14, 3],
"faces": {
"north": {"uv": [1, 2, 2, 14], "texture": "#3"},
"east": {"uv": [1, 12, 13, 16], "rotation": 270, "texture": "#belt_funnel"},
"south": {"uv": [13, 1, 14, 13], "texture": "#package_funnel_horizontal"},
"west": {"uv": [1, 12, 13, 16], "rotation": 90, "texture": "#belt_funnel"}
}
},
{
"name": "Inner",
"from": [2, 2, -1],
"to": [14, 14, 2],
"faces": {
"north": {"uv": [2, 2, 14, 14], "texture": "#3"},
"east": {"uv": [12, 2, 16, 14], "texture": "#3"},
"south": {"uv": [1, 1, 13, 13], "texture": "#package_funnel_horizontal"},
"west": {"uv": [0, 2, 4, 14], "texture": "#3"},
"up": {"uv": [2, 0, 14, 4], "texture": "#3"},
"down": {"uv": [2, 12, 14, 16], "texture": "#3"}
}
},
{
"name": "Inner",
"from": [2.1, 2.1, -2],
"to": [13.9, 13.9, -1],
"faces": {
"north": {"uv": [2, 2, 14, 14], "texture": "#brass_casing"},
"east": {"uv": [12, 2, 13, 14], "texture": "#3"},
"west": {"uv": [0, 2, 1, 14], "texture": "#3"},
"up": {"uv": [2, 0, 14, 1], "texture": "#3"},
"down": {"uv": [2, 12, 14, 13], "texture": "#3"}
}
},
{
"name": "Filter",
"from": [5, 12, 0],
"to": [11, 16, 3],
"faces": {
"north": {"uv": [6, 8, 12, 12], "texture": "#4"},
"east": {"uv": [3, 0, 6, 4], "rotation": 180, "texture": "#4"},
"south": {"uv": [6, 8, 12, 12], "texture": "#4"},
"west": {"uv": [3, 0, 6, 4], "texture": "#4"},
"up": {"uv": [6, 8, 12, 11], "texture": "#4"},
"down": {"uv": [6, 8, 12, 11], "texture": "#4"}
}
},
{
"name": "Filter",
"from": [5, 14, -1],
"to": [11, 15, 0],
"faces": {
"north": {"uv": [6, 8, 12, 9], "texture": "#4"},
"east": {"uv": [2, 0, 3, 1], "rotation": 180, "texture": "#4"},
"south": {"uv": [6, 8, 12, 9], "texture": "#4"},
"west": {"uv": [2, 0, 3, 1], "texture": "#4"},
"up": {"uv": [6, 8, 12, 9], "texture": "#4"},
"down": {"uv": [6, 8, 12, 9], "texture": "#4"}
}
}
],
"display": {
"ground": {
"translation": [0, 3, 2],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 45, 0],
"translation": [2.6, -1, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"rotation": [0, 180, 0],
"translation": [0, 0, -7],
"scale": [0.625, 0.625, 0.625]
}
}
}

View file

@ -0,0 +1,144 @@
{
"credit": "Made with Blockbench",
"textures": {
"2": "create:block/extractor",
"particle": "create:block/belt_funnel",
"belt_funnel": "create:block/belt_funnel",
"brass_casing": "create:block/brass_casing"
},
"elements": [
{
"name": "Bottom",
"from": [3, -4.1, -1],
"to": [13, -3.1, 5],
"faces": {
"north": {"uv": [0, 11, 10, 12], "texture": "#belt_funnel"},
"east": {"uv": [10, 11, 16, 12], "rotation": 180, "texture": "#belt_funnel"},
"south": {"uv": [0, 11, 10, 12], "texture": "#belt_funnel"},
"west": {"uv": [10, 11, 16, 12], "texture": "#belt_funnel"},
"up": {"uv": [10, 0, 16, 13], "rotation": 90, "texture": "#belt_funnel"},
"down": {"uv": [10, 1, 16, 11], "rotation": 270, "texture": "#belt_funnel"}
}
},
{
"name": "Top",
"from": [3, 7, -1],
"to": [13, 8, 5],
"faces": {
"north": {"uv": [0, 0, 10, 1], "texture": "#belt_funnel"},
"east": {"uv": [10, 0, 16, 1], "rotation": 180, "texture": "#belt_funnel"},
"south": {"uv": [0, 0, 10, 1], "texture": "#belt_funnel"},
"west": {"uv": [10, 0, 16, 1], "texture": "#belt_funnel"},
"up": {"uv": [10, 1, 16, 11], "rotation": 90, "texture": "#belt_funnel"},
"down": {"uv": [10, 0, 16, 13], "rotation": 90, "texture": "#belt_funnel"}
}
},
{
"name": "Side",
"from": [3, -3.1, -1],
"to": [4, 7, 5],
"faces": {
"north": {"uv": [9, 1, 10, 11.1], "texture": "#belt_funnel"},
"east": {"uv": [10, 1, 16, 11], "texture": "#belt_funnel"},
"south": {"uv": [0, 1, 1, 11.1], "texture": "#belt_funnel"},
"west": {"uv": [10, 1, 16, 11], "texture": "#belt_funnel"}
}
},
{
"name": "Center",
"from": [4, -3.1, -1],
"to": [12, 7, 4],
"faces": {
"north": {"uv": [4, 3, 12, 13.1], "texture": "#brass_casing"},
"east": {"uv": [9, 3, 10, 9], "rotation": 90, "texture": "#belt_funnel"},
"south": {"uv": [1, 1, 9, 11.1], "texture": "#belt_funnel"},
"west": {"uv": [0, 2, 1, 8], "rotation": 90, "texture": "#belt_funnel"}
}
},
{
"name": "Top",
"from": [5, 8, 0],
"to": [11, 9, 5],
"rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 0]},
"faces": {
"north": {"uv": [6, 8, 12, 9], "texture": "#2"},
"east": {"uv": [11, 1, 16, 2], "rotation": 180, "texture": "#belt_funnel"},
"south": {"uv": [6, 9, 12, 10], "texture": "#2"},
"west": {"uv": [11, 3, 16, 4], "texture": "#belt_funnel"},
"up": {"uv": [6, 10, 12, 15], "texture": "#2"},
"down": {"uv": [1, 8, 9, 13], "texture": "#belt_funnel"}
}
},
{
"name": "Ramp",
"from": [3.9, -3.1, -7.1],
"to": [12.1, 4, -1],
"rotation": {"angle": 0, "axis": "x", "origin": [8, -4, -1]},
"faces": {
"north": {"uv": [4, 0, 12.2, 7.1], "rotation": 180, "texture": "#brass_casing"},
"east": {"uv": [2, 9, 8, 16], "texture": "#brass_casing"},
"west": {"uv": [8, 9, 14, 16], "texture": "#brass_casing"},
"up": {"uv": [4, 5, 12.2, 11], "rotation": 180, "texture": "#brass_casing"},
"down": {"uv": [4, 5, 12.2, 11], "texture": "#brass_casing"}
}
},
{
"name": "Ramp",
"from": [3.9, 4, -9.1],
"to": [12.1, 7.1, -1],
"rotation": {"angle": 0, "axis": "x", "origin": [8, -4, -1]},
"faces": {
"north": {"uv": [4, 0, 12.2, 3], "texture": "#brass_casing"},
"east": {"uv": [4, 0, 12, 3], "texture": "#brass_casing"},
"west": {"uv": [4, 0, 12, 3], "texture": "#brass_casing"},
"up": {"uv": [4, 4, 12, 12], "rotation": 180, "texture": "#brass_casing"},
"down": {"uv": [4, 5, 12.2, 13], "texture": "#brass_casing"}
}
},
{
"name": "Side",
"from": [12, -3.1, -1],
"to": [13, 7, 5],
"faces": {
"north": {"uv": [0, 1, 1, 11.1], "texture": "#belt_funnel"},
"east": {"uv": [10, 1, 16, 11], "rotation": 180, "texture": "#belt_funnel"},
"south": {"uv": [9, 1, 10, 11.1], "texture": "#belt_funnel"},
"west": {"uv": [10, 1, 16, 11], "texture": "#belt_funnel"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, -149, 0],
"translation": [-0.5, 3.25, 2.25],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, -149, 0],
"translation": [-0.5, 3.25, 2.25],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 0, 2.25],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 45, 0],
"translation": [2.5, 1.75, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"rotation": [0, 180, 0],
"translation": [0, 3.5, -4.5],
"scale": [0.5, 0.5, 0.5]
}
}
}

View file

@ -1,8 +1,9 @@
{
"credit": "Made with Blockbench",
"textures": {
"belt_funnel": "create:block/belt_funnel",
"2": "create:block/extractor",
"particle": "create:block/belt_funnel",
"belt_funnel": "create:block/belt_funnel",
"brass_casing": "create:block/brass_casing"
},
"elements": [
@ -12,11 +13,11 @@
"to": [13, -3.1, 5],
"faces": {
"north": {"uv": [0, 11, 10, 12], "texture": "#belt_funnel"},
"east": {"uv": [10, 11, 16, 12], "texture": "#belt_funnel"},
"east": {"uv": [10, 11, 16, 12], "rotation": 180, "texture": "#belt_funnel"},
"south": {"uv": [0, 11, 10, 12], "texture": "#belt_funnel"},
"west": {"uv": [10, 11, 16, 12], "rotation": 180, "texture": "#belt_funnel"},
"west": {"uv": [10, 11, 16, 12], "texture": "#belt_funnel"},
"up": {"uv": [10, 0, 16, 13], "rotation": 90, "texture": "#belt_funnel"},
"down": {"uv": [10, 1, 16, 11], "rotation": 90, "texture": "#belt_funnel"}
"down": {"uv": [10, 1, 16, 11], "rotation": 270, "texture": "#belt_funnel"}
}
},
{
@ -25,9 +26,9 @@
"to": [13, 8, 5],
"faces": {
"north": {"uv": [0, 0, 10, 1], "texture": "#belt_funnel"},
"east": {"uv": [10, 0, 16, 1], "texture": "#belt_funnel"},
"east": {"uv": [10, 0, 16, 1], "rotation": 180, "texture": "#belt_funnel"},
"south": {"uv": [0, 0, 10, 1], "texture": "#belt_funnel"},
"west": {"uv": [10, 0, 16, 1], "rotation": 180, "texture": "#belt_funnel"},
"west": {"uv": [10, 0, 16, 1], "texture": "#belt_funnel"},
"up": {"uv": [10, 1, 16, 11], "rotation": 90, "texture": "#belt_funnel"},
"down": {"uv": [10, 0, 16, 13], "rotation": 90, "texture": "#belt_funnel"}
}
@ -56,39 +57,16 @@
},
{
"name": "Top",
"from": [4, 9, -1],
"to": [12, 10, 4.25],
"rotation": {"angle": 22.5, "axis": "x", "origin": [8, 8, 0]},
"from": [5, 8, 0],
"to": [11, 9, 5],
"rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 0]},
"faces": {
"north": {"uv": [1, 12, 9, 13], "rotation": 180, "texture": "#belt_funnel"},
"east": {"uv": [10, 5, 16, 6], "rotation": 180, "texture": "#belt_funnel"},
"south": {"uv": [9, 2, 11, 10], "rotation": 90, "texture": "#belt_funnel"},
"west": {"uv": [10, 5, 16, 6], "texture": "#belt_funnel"},
"up": {"uv": [10, 2, 16, 10], "rotation": 90, "texture": "#belt_funnel"},
"down": {"uv": [1, 8, 9, 12.8], "texture": "#belt_funnel"}
}
},
{
"name": "Top",
"from": [4, 7, -1],
"to": [12, 9, 2.5],
"rotation": {"angle": 22.5, "axis": "x", "origin": [8, 8, 0]},
"faces": {
"north": {"uv": [1, 11, 9, 13], "texture": "#belt_funnel"},
"east": {"uv": [10, 5, 14, 7], "rotation": 180, "texture": "#belt_funnel"},
"west": {"uv": [10, 5, 14, 6], "texture": "#belt_funnel"}
}
},
{
"name": "Ramp",
"from": [4, -4, -8],
"to": [12, 3, -1],
"rotation": {"angle": 45, "axis": "x", "origin": [8, -4, -1]},
"faces": {
"north": {"uv": [4, 5, 12, 12], "texture": "#brass_casing"},
"east": {"uv": [4, 9, 11, 16], "rotation": 90, "texture": "#brass_casing"},
"west": {"uv": [5, 9, 12, 16], "rotation": 270, "texture": "#brass_casing"},
"down": {"uv": [4, 0, 12, 7], "texture": "#brass_casing"}
"north": {"uv": [6, 8, 12, 9], "texture": "#2"},
"east": {"uv": [11, 1, 16, 2], "rotation": 180, "texture": "#belt_funnel"},
"south": {"uv": [6, 9, 12, 10], "texture": "#2"},
"west": {"uv": [11, 3, 16, 4], "texture": "#belt_funnel"},
"up": {"uv": [6, 10, 12, 15], "texture": "#2"},
"down": {"uv": [1, 8, 9, 13], "texture": "#belt_funnel"}
}
},
{

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/funnel/horizontal",
"textures": {
"particle": "create:block/package_funnel_vertical",
"package_funnel_horizontal": "create:block/package_funnel_vertical"
}
}

View file

@ -1,86 +1,86 @@
{
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/package_funnel_horizontal",
"brass_casing": "create:block/brass_casing",
"belt_funnel": "create:block/belt_funnel",
"package_funnel_horizontal": "create:block/package_funnel_horizontal"
},
"display": {
"gui": {
"rotation": [ 30, 45, 0 ],
"translation": [ 2.6, -1, 0 ],
"scale": [ 0.625, 0.625, 0.625 ]
},
"ground": {
"rotation": [ 0, 0, 0 ],
"translation": [ 0, 3, 2 ],
"scale": [ 0.25, 0.25, 0.25 ]
},
"fixed": {
"rotation": [ 0, 180, 0 ],
"translation": [ 0, 0, -7 ],
"scale": [ 0.625, 0.625, 0.625 ]
}
},
"elements": [
{
"name": "Cube",
"from": [ 1, 1, -1 ],
"to": [ 15, 2, 3 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 1, 14, 15, 15 ] },
"east": { "texture": "#belt_funnel", "uv": [ 13, 12, 14, 16 ], "rotation": 90 },
"south": { "texture": "#package_funnel_horizontal", "uv": [ 0, 13, 14, 14 ] },
"west": { "texture": "#belt_funnel", "uv": [ 13, 12, 14, 16 ], "rotation": 270 },
"up": { "texture": "#belt_funnel", "uv": [ 0, 12, 14, 16 ] },
"down": { "texture": "#belt_funnel", "uv": [ 0, 12, 14, 16 ] }
}
},
{
"name": "Cube",
"from": [ 1, 14, -1 ],
"to": [ 15, 15, 3 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 1, 1, 15, 2 ] },
"east": { "texture": "#belt_funnel", "uv": [ 0, 12, 1, 16 ], "rotation": 90 },
"south": { "texture": "#package_funnel_horizontal", "uv": [ 0, 0, 14, 1 ] },
"west": { "texture": "#belt_funnel", "uv": [ 0, 12, 1, 16 ], "rotation": 270 },
"up": { "texture": "#belt_funnel", "uv": [ 0, 12, 14, 16 ] },
"down": { "texture": "#belt_funnel", "uv": [ 0, 12, 14, 16 ] }
}
},
{
"name": "Cube",
"from": [ 1, 2, -1 ],
"to": [ 2, 14, 3 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 14, 2, 15, 14 ] },
"east": { "texture": "#belt_funnel", "uv": [ 1, 12, 13, 16 ], "rotation": 270 },
"south": { "texture": "#package_funnel_horizontal", "uv": [ 0, 1, 1, 13 ] },
"west": { "texture": "#belt_funnel", "uv": [ 1, 12, 13, 16 ], "rotation": 90 }
}
},
{
"name": "Cube",
"from": [ 14, 2, -1 ],
"to": [ 15, 14, 3 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 1, 2, 2, 14 ] },
"east": { "texture": "#belt_funnel", "uv": [ 1, 12, 13, 16 ], "rotation": 270 },
"south": { "texture": "#package_funnel_horizontal", "uv": [ 13, 1, 14, 13 ] },
"west": { "texture": "#belt_funnel", "uv": [ 1, 12, 13, 16 ], "rotation": 90 }
}
},
{
"name": "Inner",
"from": [ 2, 2, -1 ],
"to": [ 14, 14, 2 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 2, 2, 14, 14 ] },
"south": { "texture": "#package_funnel_horizontal", "uv": [ 1, 1, 13, 13 ] }
}
}
]
"textures": {
"3": "block/dark_oak_log_top",
"brass_casing": "create:block/brass_casing",
"belt_funnel": "create:block/belt_funnel",
"particle": "create:block/package_funnel_horizontal",
"package_funnel_horizontal": "create:block/package_funnel_horizontal"
},
"elements": [
{
"name": "Cube",
"from": [1, 1, -1],
"to": [15, 2, 3],
"faces": {
"north": {"uv": [1, 14, 15, 15], "texture": "#3"},
"east": {"uv": [0, 12, 1, 16], "rotation": 270, "texture": "#belt_funnel"},
"south": {"uv": [0, 13, 14, 14], "texture": "#package_funnel_horizontal"},
"west": {"uv": [0, 12, 1, 16], "rotation": 90, "texture": "#belt_funnel"},
"up": {"uv": [0, 12, 14, 16], "rotation": 180, "texture": "#belt_funnel"},
"down": {"uv": [0, 12, 14, 16], "texture": "#belt_funnel"}
}
},
{
"name": "Cube",
"from": [1, 14, -1],
"to": [15, 15, 3],
"faces": {
"north": {"uv": [1, 1, 15, 2], "texture": "#3"},
"east": {"uv": [13, 12, 14, 16], "rotation": 270, "texture": "#belt_funnel"},
"south": {"uv": [0, 0, 14, 1], "texture": "#package_funnel_horizontal"},
"west": {"uv": [13, 12, 14, 16], "rotation": 90, "texture": "#belt_funnel"},
"up": {"uv": [0, 12, 14, 16], "rotation": 180, "texture": "#belt_funnel"},
"down": {"uv": [0, 12, 14, 16], "texture": "#belt_funnel"}
}
},
{
"name": "Cube",
"from": [1, 2, -1],
"to": [2, 14, 3],
"faces": {
"north": {"uv": [14, 2, 15, 14], "texture": "#3"},
"east": {"uv": [1, 12, 13, 16], "rotation": 270, "texture": "#belt_funnel"},
"south": {"uv": [0, 1, 1, 13], "texture": "#package_funnel_horizontal"},
"west": {"uv": [1, 12, 13, 16], "rotation": 90, "texture": "#belt_funnel"}
}
},
{
"name": "Cube",
"from": [14, 2, -1],
"to": [15, 14, 3],
"faces": {
"north": {"uv": [1, 2, 2, 14], "texture": "#3"},
"east": {"uv": [1, 12, 13, 16], "rotation": 270, "texture": "#belt_funnel"},
"south": {"uv": [13, 1, 14, 13], "texture": "#package_funnel_horizontal"},
"west": {"uv": [1, 12, 13, 16], "rotation": 90, "texture": "#belt_funnel"}
}
},
{
"name": "Inner",
"from": [2, 2, -1],
"to": [14, 14, 2],
"faces": {
"north": {"uv": [2, 2, 14, 14], "texture": "#brass_casing"},
"south": {"uv": [1, 1, 13, 13], "texture": "#package_funnel_horizontal"}
}
}
],
"display": {
"ground": {
"translation": [0, 3, 2],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 45, 0],
"translation": [2.6, -1, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"rotation": [0, 180, 0],
"translation": [0, 0, -7],
"scale": [0.625, 0.625, 0.625]
}
}
}

View file

@ -0,0 +1,197 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"1": "create:block/brass_casing",
"2": "create:block/transposer",
"particle": "create:block/extractor",
"extractor": "create:block/extractor"
},
"elements": [
{
"name": "Bottom",
"from": [4, 4, -1],
"to": [12, 5, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"north": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"up": {"uv": [0, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 8], "rotation": 270, "texture": "#extractor"}
}
},
{
"name": "Side",
"from": [11, 5, 15],
"to": [12, 11, 17],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 20]},
"faces": {
"north": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"east": {"uv": [4, 0, 6, 1], "texture": "#extractor"},
"south": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"west": {"uv": [4, 0, 6, 6], "texture": "#extractor"}
}
},
{
"name": "Side",
"from": [4, 5, 15],
"to": [5, 11, 17],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 20]},
"faces": {
"north": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"east": {"uv": [4, 0, 6, 6], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"west": {"uv": [4, 0, 6, 1], "rotation": 180, "texture": "#extractor"}
}
},
{
"name": "Top",
"from": [4, 11, 15],
"to": [12, 12.05, 17],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 20]},
"faces": {
"north": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"east": {"uv": [4, 0, 6, 1], "texture": "#extractor"},
"south": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"west": {"uv": [4, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"up": {"uv": [4, 0, 6, 8], "rotation": 270, "texture": "#extractor"},
"down": {"uv": [0, 0, 2, 8], "rotation": 90, "texture": "#extractor"}
}
},
{
"name": "Bottom",
"from": [4, 4, 15],
"to": [12, 5, 17],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 20]},
"faces": {
"north": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"east": {"uv": [4, 0, 6, 1], "texture": "#extractor"},
"south": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"west": {"uv": [4, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"up": {"uv": [4, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [4, 0, 6, 8], "rotation": 90, "texture": "#extractor"}
}
},
{
"name": "FilterSpot",
"from": [5, 12, -1],
"to": [11, 13.05, 4],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 13, -1]},
"faces": {
"north": {"uv": [0, 9, 1, 15], "rotation": 90, "texture": "#extractor"},
"east": {"uv": [0, 9, 5, 10], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [4, 9, 5, 15], "rotation": 270, "texture": "#extractor"},
"west": {"uv": [0, 9, 5, 10], "texture": "#extractor"},
"up": {"uv": [0, 9, 5, 15], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 0, 0], "texture": "#extractor"}
}
},
{
"name": "Center",
"from": [5, 5, 0],
"to": [11, 11, 16],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"east": {"uv": [0, 0, 16, 6], "rotation": 180, "texture": "#2"},
"south": {"uv": [7, 1, 13, 7], "texture": "#extractor"},
"west": {"uv": [0, 0, 16, 6], "texture": "#2"},
"up": {"uv": [0, 0, 16, 6], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 16, 6], "rotation": 270, "texture": "#2"}
}
},
{
"name": "Side",
"from": [11, 5, -1],
"to": [12, 11, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"north": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
}
},
{
"name": "Side",
"from": [4, 5, -1],
"to": [5, 11, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"north": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
}
},
{
"name": "Top",
"from": [4, 11, -1],
"to": [12, 12, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"north": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"up": {"uv": [0, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 8], "rotation": 270, "texture": "#extractor"}
}
},
{
"name": "Extension",
"from": [4.9, 4.9, -3],
"to": [11.1, 11.1, -1],
"faces": {
"north": {"uv": [5, 5, 11, 11], "rotation": 180, "texture": "#1"},
"east": {"uv": [3, 0, 5, 6], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [0, 0, 0, 0], "texture": "#extractor"},
"west": {"uv": [3, 0, 5, 6], "texture": "#extractor"},
"up": {"uv": [3, 0, 5, 6], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [3, 0, 5, 6], "rotation": 270, "texture": "#extractor"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, -149, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, -149, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 1, 1.25],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 45, 0],
"translation": [0, -0.25, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"rotation": [0, 180, 0],
"translation": [0, 1.75, -4.5],
"scale": [0.5, 0.5, 0.5]
}
},
"groups": [
{
"name": "transposer",
"origin": [8, 8, 8],
"children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}
]
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/transposer/default",
"textures": {
"extractor": "create:block/extractor_powered",
"particle": "create:block/extractor_powered"
}
}

View file

@ -0,0 +1,246 @@
{
"credit": "Made with Blockbench",
"parent": "create:block/extractor/horizontal",
"textures": {
"1": "create:block/brass_casing",
"2": "create:block/transposer",
"particle": "create:block/extractor",
"extractor": "create:block/extractor",
"redstone_antenna": "create:block/redstone_antenna"
},
"elements": [
{
"name": "Bottom",
"from": [5, 4, -1],
"to": [12, 5, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"north": {"uv": [6, 7, 13, 8], "texture": "#extractor"},
"east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 7, 13, 8], "texture": "#extractor"},
"west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"up": {"uv": [0, 0, 6, 7], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 7], "rotation": 270, "texture": "#extractor"}
}
},
{
"name": "Side",
"from": [11, 5, 15],
"to": [12, 11, 17],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 20]},
"faces": {
"north": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"east": {"uv": [4, 0, 6, 1], "texture": "#extractor"},
"south": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"west": {"uv": [4, 0, 6, 6], "texture": "#extractor"},
"up": {"uv": [0, 0, 0, 0], "texture": "#extractor"},
"down": {"uv": [0, 0, 0, 0], "texture": "#extractor"}
}
},
{
"name": "Side",
"from": [4, 5, 15],
"to": [5, 11, 17],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 20]},
"faces": {
"north": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"east": {"uv": [4, 0, 6, 6], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"west": {"uv": [4, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"up": {"uv": [0, 0, 0, 0], "texture": "#extractor"},
"down": {"uv": [0, 0, 0, 0], "texture": "#extractor"}
}
},
{
"name": "Top",
"from": [4, 11, 15],
"to": [12, 12.05, 17],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 20]},
"faces": {
"north": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"east": {"uv": [4, 0, 6, 1], "texture": "#extractor"},
"south": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"west": {"uv": [4, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"up": {"uv": [4, 0, 6, 8], "rotation": 270, "texture": "#extractor"},
"down": {"uv": [0, 0, 2, 8], "rotation": 90, "texture": "#extractor"}
}
},
{
"name": "Bottom",
"from": [4, 4, 15],
"to": [12, 5, 17],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 20]},
"faces": {
"north": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"east": {"uv": [4, 0, 6, 1], "texture": "#extractor"},
"south": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"west": {"uv": [4, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"up": {"uv": [4, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [4, 0, 6, 8], "rotation": 90, "texture": "#extractor"}
}
},
{
"name": "FilterSpot",
"from": [5, 12, -1],
"to": [11, 13.05, 4],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 13, -1]},
"faces": {
"north": {"uv": [0, 9, 1, 15], "rotation": 90, "texture": "#extractor"},
"east": {"uv": [0, 9, 5, 10], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [4, 9, 5, 15], "rotation": 270, "texture": "#extractor"},
"west": {"uv": [0, 9, 5, 10], "texture": "#extractor"},
"up": {"uv": [0, 9, 5, 15], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 0, 0], "texture": "#extractor"}
}
},
{
"name": "Center",
"from": [5, 5, 0],
"to": [11, 11, 16],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"east": {"uv": [0, 0, 16, 6], "rotation": 180, "texture": "#2"},
"south": {"uv": [7, 1, 13, 7], "texture": "#extractor"},
"west": {"uv": [0, 0, 16, 6], "texture": "#2"},
"up": {"uv": [0, 0, 16, 6], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 16, 6], "rotation": 270, "texture": "#2"}
}
},
{
"name": "Side",
"from": [11, 5, -1],
"to": [12, 11, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"north": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"},
"up": {"uv": [0, 0, 0, 0], "texture": "#extractor"},
"down": {"uv": [0, 0, 0, 0], "texture": "#extractor"}
}
},
{
"name": "Top",
"from": [5, 11, -1],
"to": [12, 12, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"north": {"uv": [6, 0, 13, 1], "texture": "#extractor"},
"east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 0, 13, 1], "texture": "#extractor"},
"west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"up": {"uv": [0, 0, 6, 7], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 7], "rotation": 270, "texture": "#extractor"}
}
},
{
"name": "Extension",
"from": [4.9, 4.9, -3],
"to": [11.1, 11.1, -1],
"faces": {
"north": {"uv": [5, 5, 11, 11], "rotation": 180, "texture": "#1"},
"east": {"uv": [3, 0, 5, 6], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [0, 0, 0, 0], "texture": "#extractor"},
"west": {"uv": [3, 0, 5, 6], "texture": "#extractor"},
"up": {"uv": [3, 0, 5, 6], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [3, 0, 5, 6], "rotation": 270, "texture": "#extractor"}
}
},
{
"name": "AntennaDish",
"from": [10, 15, 0],
"to": [15, 15, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"up": {"uv": [4, 0, 9, 5], "texture": "#redstone_antenna"},
"down": {"uv": [4, 0, 9, 5], "texture": "#redstone_antenna"}
}
},
{
"name": "AntennaX",
"from": [11, 9, 2],
"to": [14, 19, 3],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"north": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"south": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"down": {"uv": [0, 9, 3, 10], "texture": "#redstone_antenna"}
}
},
{
"name": "AntennaZ",
"from": [12, 9, 1],
"to": [13, 19, 4],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"east": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"west": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"}
}
},
{
"name": "AntennaTop",
"from": [12, 17, 2],
"to": [13, 18, 3],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"up": {"uv": [1, 1, 2, 2], "texture": "#redstone_antenna"}
}
},
{
"name": "Side",
"from": [4, 4, -1],
"to": [5, 12, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"north": {"uv": [13, 0, 14, 8], "texture": "#extractor"},
"east": {"uv": [0, 1, 6, 9], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 1, 7, 9], "texture": "#extractor"},
"west": {"uv": [6, 8, 12, 16], "texture": "#extractor"},
"up": {"uv": [6, 15, 12, 16], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [6, 15, 12, 16], "rotation": 90, "texture": "#extractor"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, -149, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, -149, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 1, 1.25],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 45, 0],
"translation": [0, -0.25, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"rotation": [0, 180, 0],
"translation": [0, 1.75, -4.5],
"scale": [0.5, 0.5, 0.5]
}
},
"groups": [
{
"name": "transposer",
"origin": [8, 8, 8],
"children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
}
]
}

View file

@ -0,0 +1,8 @@
{
"parent": "create:block/transposer/linked",
"textures": {
"redstone_antenna": "create:block/redstone_antenna_powered",
"extractor": "create:block/extractor_powered",
"particle": "create:block/extractor_powered"
}
}

View file

@ -0,0 +1,249 @@
{
"credit": "Made with Blockbench",
"parent": "create:block/extractor/horizontal",
"textures": {
"1": "create:block/brass_casing",
"2": "create:block/transposer",
"particle": "create:block/extractor",
"extractor": "create:block/extractor",
"redstone_antenna": "create:block/redstone_antenna"
},
"elements": [
{
"name": "Side",
"from": [11, 5, 15],
"to": [12, 11, 17],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 20]},
"faces": {
"north": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"east": {"uv": [4, 0, 6, 1], "texture": "#extractor"},
"south": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"west": {"uv": [4, 0, 6, 6], "texture": "#extractor"},
"up": {"uv": [0, 0, 0, 0], "texture": "#extractor"},
"down": {"uv": [0, 0, 0, 0], "texture": "#extractor"}
}
},
{
"name": "Side",
"from": [4, 5, 15],
"to": [5, 11, 17],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 20]},
"faces": {
"north": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"east": {"uv": [4, 0, 6, 6], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"west": {"uv": [4, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"up": {"uv": [0, 0, 0, 0], "texture": "#extractor"},
"down": {"uv": [0, 0, 0, 0], "texture": "#extractor"}
}
},
{
"name": "Top",
"from": [4, 11, 15],
"to": [12, 12.05, 17],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 20]},
"faces": {
"north": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"east": {"uv": [4, 0, 6, 1], "texture": "#extractor"},
"south": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"west": {"uv": [4, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"up": {"uv": [4, 0, 6, 8], "rotation": 270, "texture": "#extractor"},
"down": {"uv": [0, 0, 2, 8], "rotation": 90, "texture": "#extractor"}
}
},
{
"name": "Bottom",
"from": [4, 4, 15],
"to": [12, 5, 17],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 20]},
"faces": {
"north": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"east": {"uv": [4, 0, 6, 1], "texture": "#extractor"},
"south": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"west": {"uv": [4, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"up": {"uv": [4, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [4, 0, 6, 8], "rotation": 90, "texture": "#extractor"}
}
},
{
"name": "FilterSpot",
"from": [5, 12, -1],
"to": [11, 13.05, 4],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 13, -1]},
"faces": {
"north": {"uv": [0, 9, 1, 15], "rotation": 90, "texture": "#extractor"},
"east": {"uv": [0, 9, 5, 10], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [4, 9, 5, 15], "rotation": 270, "texture": "#extractor"},
"west": {"uv": [0, 9, 5, 10], "texture": "#extractor"},
"up": {"uv": [0, 9, 5, 15], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 0, 0], "texture": "#extractor"}
}
},
{
"name": "Center",
"from": [5, 5, 0],
"to": [11, 11, 16],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
"faces": {
"east": {"uv": [0, 0, 16, 6], "rotation": 180, "texture": "#2"},
"south": {"uv": [7, 1, 13, 7], "texture": "#extractor"},
"west": {"uv": [0, 0, 16, 6], "texture": "#2"},
"up": {"uv": [0, 0, 16, 6], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 16, 6], "rotation": 270, "texture": "#2"}
}
},
{
"name": "Extension",
"from": [4.9, 4.9, -3],
"to": [11.1, 11.1, -1],
"faces": {
"north": {"uv": [5, 5, 11, 11], "rotation": 180, "texture": "#1"},
"east": {"uv": [3, 0, 5, 6], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [0, 0, 0, 0], "texture": "#extractor"},
"west": {"uv": [3, 0, 5, 6], "texture": "#extractor"},
"up": {"uv": [3, 0, 5, 6], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [3, 0, 5, 6], "rotation": 270, "texture": "#extractor"}
}
},
{
"name": "AntennaDish",
"from": [10, 15, 0],
"to": [15, 15, 5],
"rotation": {"angle": 0, "axis": "x", "origin": [13, 9, 3]},
"faces": {
"up": {"uv": [4, 0, 9, 5], "texture": "#redstone_antenna"},
"down": {"uv": [4, 0, 9, 5], "texture": "#redstone_antenna"}
}
},
{
"name": "AntennaX",
"from": [11, 9, 2],
"to": [14, 19, 3],
"rotation": {"angle": 0, "axis": "x", "origin": [13, 9, 3]},
"faces": {
"north": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"south": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"down": {"uv": [0, 9, 3, 10], "texture": "#redstone_antenna"}
}
},
{
"name": "AntennaZ",
"from": [12, 9, 1],
"to": [13, 19, 4],
"rotation": {"angle": 0, "axis": "x", "origin": [13, 9, 3]},
"faces": {
"east": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"west": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"}
}
},
{
"name": "AntennaTop",
"from": [12, 17, 2],
"to": [13, 18, 3],
"rotation": {"angle": 0, "axis": "x", "origin": [13, 9, 3]},
"faces": {
"up": {"uv": [1, 1, 2, 2], "texture": "#redstone_antenna"}
}
},
{
"name": "Bottom",
"from": [4, 4, -1],
"to": [12, 5, 5],
"faces": {
"north": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"east": {"uv": [6, 8, 12, 9], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"west": {"uv": [6, 15, 12, 16], "texture": "#extractor"},
"up": {"uv": [0, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [6, 8, 12, 16], "rotation": 270, "texture": "#extractor"}
}
},
{
"name": "Top",
"from": [4, 11, -1],
"to": [12, 12, 5],
"faces": {
"north": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"up": {"uv": [0, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 8], "rotation": 270, "texture": "#extractor"}
}
},
{
"name": "Side",
"from": [4, 5, -1],
"to": [5, 11, 5],
"faces": {
"north": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
}
},
{
"name": "Side",
"from": [11, 5, -1],
"to": [12, 11, 5],
"faces": {
"north": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, -149, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, -149, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 1, 1.25],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 45, 0],
"translation": [2.5, -0.5, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"rotation": [0, 180, 0],
"translation": [0, 1.75, -4.5],
"scale": [0.5, 0.5, 0.5]
}
},
"groups": [
{
"name": "transposer",
"origin": [8, 8, 8],
"children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
},
{
"name": "vertical_wireless",
"origin": [8, 8, 8],
"children": [
{
"name": "vertical",
"origin": [8, 8, 8],
"children": [11, 12, 13, 14]
}
]
}
]
}

View file

@ -0,0 +1,8 @@
{
"parent": "create:block/transposer/vertical_linked",
"textures": {
"redstone_antenna": "create:block/redstone_antenna_powered",
"extractor": "create:block/extractor_powered",
"particle": "create:block/extractor_powered"
}
}

View file

@ -1,110 +1,3 @@
{
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
"textures": {
"particle": "create:block/belt_funnel",
"belt_funnel": "create:block/belt_funnel",
"brass_casing": "create:block/brass_casing"
},
"display": {
"gui": {
"rotation": [ 30, 45, 0 ],
"translation": [ 2, 2, 0 ],
"scale": [ 0.625, 0.625, 0.625 ]
},
"ground": {
"rotation": [ 0, 0, 0 ],
"translation": [ 0, 3, 2 ],
"scale": [ 0.25, 0.25, 0.25 ]
},
"fixed": {
"rotation": [ 0, 180, 0 ],
"translation": [ 0, 3, -2.75 ],
"scale": [ 0.5, 0.5, 0.5 ]
},
"firstperson_righthand": {
"rotation": [ 0, 180, 0 ],
"translation": [ 0, 2.5, 0 ],
"scale": [ 0.4, 0.4, 0.4 ]
},
"thirdperson_righthand": {
"rotation": [ 75, 45, 0 ],
"translation": [ 0, 2.5, 0 ],
"scale": [ 0.375, 0.375, 0.375 ]
}
},
"elements": [
{
"name": "Bottom",
"from": [ 3, -4.1, -1 ],
"to": [ 13, -3.1, 5 ],
"faces": {
"north": { "texture": "#belt_funnel", "uv": [ 0, 11, 10, 12 ] },
"east": { "texture": "#belt_funnel", "uv": [ 10, 11, 16, 12 ] },
"south": { "texture": "#belt_funnel", "uv": [ 0, 11, 10, 12 ] },
"west": { "texture": "#belt_funnel", "uv": [ 10, 11, 16, 12 ], "rotation": 180 },
"up": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 13 ], "rotation": 90 },
"down": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 12 ], "rotation": 90 }
}
},
{
"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": [ 10, 0, 16, 1 ] },
"south": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] },
"west": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 1 ], "rotation": 180 },
"up": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 12 ], "rotation": 90 },
"down": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 13 ], "rotation": 90 }
}
},
{
"name": "Side",
"from": [ 3, -3.1, -1 ],
"to": [ 4, 7, 5 ],
"faces": {
"north": { "texture": "#belt_funnel", "uv": [ 9, 1, 10, 11.1 ] },
"east": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ] },
"south": { "texture": "#belt_funnel", "uv": [ 0, 1, 1, 11.1 ] },
"west": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ] }
}
},
{
"name": "Center",
"from": [ 4, -3.1, -1 ],
"to": [ 12, 7, 4 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 4, 3, 12, 13.1 ] },
"east": { "texture": "#belt_funnel", "uv": [ 9, 3, 10, 9 ], "rotation": 90 },
"south": { "texture": "#belt_funnel", "uv": [ 1, 1, 9, 11.1 ] },
"west": { "texture": "#belt_funnel", "uv": [ 0, 2, 1, 8 ], "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": [ 11, 4.6, 16, 6.6 ], "rotation": 180 },
"south": { "texture": "#belt_funnel", "uv": [ 9, 2, 11, 10 ], "rotation": 90 },
"west": { "texture": "#belt_funnel", "uv": [ 10, 5, 15, 7.4 ], "rotation": 180 },
"up": { "texture": "#belt_funnel", "uv": [ 11, 2, 16, 9.4 ], "rotation": 90 },
"down": { "texture": "#belt_funnel", "uv": [ 1, 8, 9, 12.8 ] }
}
},
{
"name": "Side",
"from": [ 12, -3.1, -1 ],
"to": [ 13, 7, 5 ],
"faces": {
"north": { "texture": "#belt_funnel", "uv": [ 0, 1, 1, 11.1 ] },
"east": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ], "rotation": 180 },
"south": { "texture": "#belt_funnel", "uv": [ 9, 1, 10, 11.1 ] },
"west": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ] }
}
}
]
"parent": "create:block/funnel/item"
}

View file

@ -0,0 +1,3 @@
{
"parent": "create:block/transposer/linked"
}

View file

@ -0,0 +1,3 @@
{
"parent": "create:block/transposer/default"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 531 B

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 B

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 600 B

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 441 B

Some files were not shown because too many files have changed in this diff Show more