Spinny vortex

- Crushing wheels no longer z-fight with chutes
- Improved rendering of items and fluids inside basins
This commit is contained in:
simibubi 2020-11-06 19:45:38 +01:00
parent d5f08aab76
commit dbfe7f93fa
16 changed files with 672 additions and 197 deletions

View file

@ -30,6 +30,7 @@ public enum AllParticleTypes {
HEATER_PARTICLE(HeaterParticleData::new),
CUBE(CubeParticleData::new),
FLUID_PARTICLE(FluidParticleData::new),
BASIN_FLUID(FluidParticleData::new),
FLUID_DRIP(FluidParticleData::new)
;

View file

@ -5,6 +5,7 @@ import java.util.Optional;
import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity;
import com.simibubi.create.content.contraptions.fluids.FluidFX;
import com.simibubi.create.content.contraptions.fluids.potion.PotionMixingRecipeManager;
import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity;
import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
@ -12,6 +13,8 @@ import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.advancement.ITriggerable;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.item.SmartInventory;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.inventory.IInventory;
@ -19,6 +22,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntityType;
@ -86,6 +90,9 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
running = compound.getBoolean("Running");
runningTicks = compound.getInt("Ticks");
super.read(compound, clientPacket);
if (clientPacket && hasWorld())
getBasin().ifPresent(bte -> bte.setAreFluidsMoving(running && runningTicks <= 20));
}
@Override
@ -127,7 +134,6 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
if (runningTicks != 20)
runningTicks++;
}
}
public void renderParticles() {
@ -135,24 +141,38 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
if (!basin.isPresent() || world == null)
return;
SmartInventory inputs = basin.get()
.getInputInventory();
for (int slot = 0; slot < inputs.getSlots(); slot++) {
ItemStack stackInSlot = inputs.getStackInSlot(slot);
if (stackInSlot.isEmpty())
continue;
ItemParticleData data = new ItemParticleData(ParticleTypes.ITEM, stackInSlot);
float angle = world.rand.nextFloat() * 360;
Vec3d offset = new Vec3d(0, 0, 0.25f);
offset = VecHelper.rotate(offset, angle, Axis.Y);
Vec3d target = VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y)
.add(0, .25f, 0);
Vec3d center = offset.add(VecHelper.getCenterOf(pos));
target = VecHelper.offsetRandomly(target.subtract(offset), world.rand, 1 / 128f);
world.addParticle(data, center.x, center.y - 2, center.z, target.x, target.y, target.z);
for (SmartInventory inv : basin.get()
.getInvs()) {
for (int slot = 0; slot < inv.getSlots(); slot++) {
ItemStack stackInSlot = inv.getStackInSlot(slot);
if (stackInSlot.isEmpty())
continue;
ItemParticleData data = new ItemParticleData(ParticleTypes.ITEM, stackInSlot);
spillParticle(data);
}
}
for (SmartFluidTankBehaviour behaviour : basin.get()
.getTanks()) {
if (behaviour == null)
continue;
for (TankSegment tankSegment : behaviour.getTanks()) {
if (tankSegment.isEmpty(0))
continue;
spillParticle(FluidFX.getFluidParticle(tankSegment.getRenderedFluid()));
}
}
}
protected void spillParticle(IParticleData data) {
float angle = world.rand.nextFloat() * 360;
Vec3d offset = new Vec3d(0, 0, 0.25f);
offset = VecHelper.rotate(offset, angle, Axis.Y);
Vec3d target = VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y)
.add(0, .25f, 0);
Vec3d center = offset.add(VecHelper.getCenterOf(pos));
target = VecHelper.offsetRandomly(target.subtract(offset), world.rand, 1 / 128f);
world.addParticle(data, center.x, center.y - 1.75f, center.z, target.x, target.y, target.z);
}
@Override

View file

@ -45,10 +45,6 @@ public class FluidFX {
}
public static IParticleData getFluidParticle(FluidStack fluid) {
if (FluidHelper.hasBlockState(fluid.getFluid()))
return new BlockParticleData(ParticleTypes.BLOCK, fluid.getFluid()
.getDefaultState()
.getBlockState());
return new FluidParticleData(AllParticleTypes.FLUID_PARTICLE.get(), fluid);
}
@ -82,17 +78,17 @@ public class FluidFX {
public static void spawnPouringLiquid(World world, BlockPos pos, int amount, IParticleData particle,
float rimRadius, Vec3d directionVec, boolean inbound) {
for (int i = 0; i < amount; i++) {
Vec3d vec = VecHelper.offsetRandomly(Vec3d.ZERO, r, rimRadius);
Vec3d vec = VecHelper.offsetRandomly(Vec3d.ZERO, r, rimRadius * .75f);
vec = vec.mul(VecHelper.axisAlingedPlaneOf(directionVec))
.add(directionVec.scale(.5 + r.nextFloat() / 4f));
Vec3d m = vec;
Vec3d m = vec.scale(1 / 4f);
Vec3d centerOf = VecHelper.getCenterOf(pos);
vec = vec.add(centerOf);
if (inbound) {
vec = vec.add(m);
m = centerOf.add(directionVec.scale(.5))
.subtract(vec)
.scale(3);
.scale(1 / 16f);
}
world.addOptionalParticle(particle, vec.x, vec.y - 1 / 16f, vec.z, m.x, m.y, m.z);
}

View file

@ -0,0 +1,100 @@
package com.simibubi.create.content.contraptions.fluids.particle;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.processing.BasinTileEntity;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.Quaternion;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
public class BasinFluidParticle extends FluidStackParticle {
BlockPos basinPos;
Vec3d targetPos;
Vec3d centerOfBasin;
float yOffset;
public BasinFluidParticle(World world, FluidStack fluid, double x, double y, double z, double vx, double vy,
double vz) {
super(world, fluid, x, y, z, vx, vy, vz);
particleGravity = 0;
motionX = 0;
motionY = 0;
motionZ = 0;
yOffset = world.rand.nextFloat() * 1 / 32f;
posY += yOffset;
particleScale = 0;
maxAge = 60;
Vec3d currentPos = new Vec3d(posX, posY, posZ);
basinPos = new BlockPos(currentPos);
centerOfBasin = VecHelper.getCenterOf(basinPos);
if (vx != 0) {
maxAge = 20;
Vec3d centerOf = VecHelper.getCenterOf(basinPos);
Vec3d diff = currentPos.subtract(centerOf)
.mul(1, 0, 1)
.normalize()
.scale(.375);
targetPos = centerOf.add(diff);
prevPosX = posX = centerOfBasin.x;
prevPosZ = posZ = centerOfBasin.z;
}
}
@Override
public void tick() {
super.tick();
particleScale = targetPos != null ? Math.max(1 / 32f, ((1f * age) / maxAge) / 8)
: 1 / 8f * (1 - ((Math.abs(age - (maxAge / 2)) / (1f * maxAge))));
if (age % 2 == 0) {
if (!AllBlocks.BASIN.has(world.getBlockState(basinPos))) {
setExpired();
return;
}
TileEntity tileEntity = world.getTileEntity(basinPos);
if (tileEntity instanceof BasinTileEntity) {
float totalUnits = ((BasinTileEntity) tileEntity).getTotalFluidUnits();
if (totalUnits < 1)
totalUnits = 0;
float fluidLevel = MathHelper.clamp(totalUnits / 2000, 0, 1);
posY = 2 / 16f + basinPos.getY() + 12 / 16f * fluidLevel + yOffset;
}
}
if (targetPos != null) {
float progess = (1f * age) / maxAge;
Vec3d currentPos = centerOfBasin.add(targetPos.subtract(centerOfBasin)
.scale(progess));
posX = currentPos.x;
posZ = currentPos.z;
}
}
@Override
public void buildGeometry(IVertexBuilder vb, ActiveRenderInfo info, float pt) {
Quaternion rotation = info.getRotation();
Quaternion prevRotation = new Quaternion(rotation);
rotation.set(1, 0, 0, 1);
rotation.normalize();
super.buildGeometry(vb, info, pt);
rotation.set(0, 0, 0, 1);
rotation.multiply(prevRotation);
}
@Override
protected boolean canEvaporate() {
return false;
}
}

View file

@ -30,7 +30,8 @@ public class FluidParticleData implements IParticleData, ICustomParticleData<Flu
@Override
@OnlyIn(Dist.CLIENT)
public IParticleFactory<FluidParticleData> getFactory() {
return (data, world, x, y, z, vx, vy, vz) -> new FluidStackParticle(world, data.fluid, x, y, z, vx, vy, vz);
return (data, world, x, y, z, vx, vy, vz) -> FluidStackParticle.create(data.type, world, data.fluid, x, y, z,
vx, vy, vz);
}
@Override

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.contraptions.fluids.particle;
import com.simibubi.create.AllParticleTypes;
import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid;
import com.simibubi.create.foundation.utility.ColorHelper;
@ -7,6 +8,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.IParticleRenderType;
import net.minecraft.client.particle.SpriteTexturedParticle;
import net.minecraft.inventory.container.PlayerContainer;
import net.minecraft.particles.ParticleType;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
@ -17,6 +19,13 @@ public class FluidStackParticle extends SpriteTexturedParticle {
private final float field_217588_H;
private FluidStack fluid;
public static FluidStackParticle create(ParticleType<FluidParticleData> type, World world, FluidStack fluid, double x,
double y, double z, double vx, double vy, double vz) {
if (type == AllParticleTypes.BASIN_FLUID.get())
return new BasinFluidParticle(world, fluid, x, y, z, vx, vy, vz);
return new FluidStackParticle(world, fluid, x, y, z, vx, vy, vz);
}
public FluidStackParticle(World world, FluidStack fluid, double x, double y, double z, double vx, double vy,
double vz) {
super(world, x, y, z, vx, vy, vz);
@ -34,14 +43,25 @@ public class FluidStackParticle extends SpriteTexturedParticle {
this.multiplyColor(fluid.getFluid()
.getAttributes()
.getColor(fluid));
this.motionX = vx;
this.motionY = vy;
this.motionZ = vz;
this.particleScale /= 2.0F;
this.field_217587_G = this.rand.nextFloat() * 3.0F;
this.field_217588_H = this.rand.nextFloat() * 3.0F;
}
public IParticleRenderType getRenderType() {
return IParticleRenderType.TERRAIN_SHEET;
@Override
protected int getBrightnessForRender(float p_189214_1_) {
int brightnessForRender = super.getBrightnessForRender(p_189214_1_);
int skyLight = brightnessForRender >> 20;
int blockLight = (brightnessForRender >> 4) & 0xf;
blockLight = Math.max(blockLight, fluid.getFluid()
.getAttributes()
.getLuminosity(fluid));
return (skyLight << 20) | (blockLight << 4);
}
protected void multiplyColor(int color) {
@ -69,13 +89,13 @@ public class FluidStackParticle extends SpriteTexturedParticle {
@Override
public void tick() {
super.tick();
if (!(fluid.getFluid() instanceof PotionFluid))
if (!canEvaporate())
return;
if (onGround)
setExpired();
if (!isExpired)
return;
if (!onGround && world.rand.nextFloat() < 1/8f)
if (!onGround && world.rand.nextFloat() < 1 / 8f)
return;
Vec3d rgb = ColorHelper.getRGB(fluid.getFluid()
@ -83,5 +103,14 @@ public class FluidStackParticle extends SpriteTexturedParticle {
.getColor(fluid));
world.addParticle(ParticleTypes.ENTITY_EFFECT, posX, posY, posZ, rgb.x, rgb.y, rgb.z);
}
protected boolean canEvaporate() {
return fluid.getFluid() instanceof PotionFluid;
}
@Override
public IParticleRenderType getRenderType() {
return IParticleRenderType.TERRAIN_SHEET;
}
}

View file

@ -7,14 +7,20 @@ import com.simibubi.create.foundation.fluid.FluidRenderer;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment;
import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.IntAttached;
import com.simibubi.create.foundation.utility.MatrixStacker;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
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.MathHelper;
import net.minecraft.util.math.Vec3d;
@ -33,35 +39,92 @@ public class BasinRenderer extends SmartTileEntityRenderer<BasinTileEntity> {
int light, int overlay) {
super.renderSafe(basin, partialTicks, ms, buffer, light, overlay);
renderFluids(basin, partialTicks, ms, buffer, light, overlay);
float fluidLevel = renderFluids(basin, partialTicks, ms, buffer, light, overlay);
float level = MathHelper.clamp(fluidLevel - .3f, .125f, .6f);
ms.push();
BlockPos pos = basin.getPos();
ms.translate(.5, .2f, .5);
MatrixStacker.of(ms)
.rotateY(basin.ingredientRotation.getValue(partialTicks));
Random r = new Random(pos.hashCode());
Vec3d baseVector = new Vec3d(.125, level, 0);
IItemHandlerModifiable inv = basin.itemCapability.orElse(new ItemStackHandler());
int itemCount = 0;
for (int slot = 0; slot < inv.getSlots(); slot++)
if (!inv.getStackInSlot(slot)
.isEmpty())
itemCount++;
if (itemCount == 1)
baseVector = new Vec3d(0, level, 0);
float anglePartition = 360f / itemCount;
for (int slot = 0; slot < inv.getSlots(); slot++) {
ItemStack stack = inv.getStackInSlot(slot);
if (stack.isEmpty())
continue;
ms.push();
if (fluidLevel > 0) {
ms.translate(0,
(MathHelper.sin(AnimationTickHolder.getRenderTick() / 12f + anglePartition * itemCount) + 1.5f) * 1
/ 32f,
0);
}
Vec3d itemPosition = VecHelper.rotate(baseVector, anglePartition * itemCount, Axis.Y);
ms.translate(itemPosition.x, itemPosition.y, itemPosition.z);
MatrixStacker.of(ms)
.rotateY(anglePartition * itemCount + 35)
.rotateX(65);
for (int i = 0; i <= stack.getCount() / 8; i++) {
ms.push();
Vec3d vec = VecHelper.offsetRandomly(Vec3d.ZERO, r, .25f);
Vec3d vec2 = VecHelper.offsetRandomly(Vec3d.ZERO, r, .5f);
Vec3d vec = VecHelper.offsetRandomly(Vec3d.ZERO, r, 1 / 16f);
ms.translate(vec.x, vec.y, vec.z);
ms.multiply(new Vector3f((float) vec2.z, (float) vec2.y, 0).getDegreesQuaternion((float) vec2.x * 180));
Minecraft.getInstance()
.getItemRenderer()
.renderItem(stack, TransformType.GROUND, light, overlay, ms, buffer);
renderItem(ms, buffer, light, overlay, stack);
ms.pop();
}
ms.translate(0, 1 / 64f, 0);
ms.pop();
itemCount--;
}
ms.pop();
BlockState blockState = basin.getBlockState();
if (!(blockState.getBlock() instanceof BasinBlock))
return;
Direction direction = blockState.get(BasinBlock.FACING);
if (direction == Direction.DOWN)
return;
Vec3d directionVec = new Vec3d(direction.getDirectionVec());
Vec3d outVec = VecHelper.getCenterOf(BlockPos.ZERO)
.add(directionVec.scale(.55)
.subtract(0, 1 / 2f, 0));
for (IntAttached<ItemStack> intAttached : basin.visualizedOutputItems) {
float progress = 1 - (intAttached.getFirst() - partialTicks) / BasinTileEntity.OUTPUT_ANIMATION_TIME;
ms.push();
MatrixStacker.of(ms)
.translate(outVec)
.translate(new Vec3d(0, Math.max(-.55f, -(progress * progress * 2)), 0))
.translate(directionVec.scale(progress * .5f))
.rotateY(AngleHelper.horizontalAngle(direction))
.rotateX(progress * 180);
renderItem(ms, buffer, light, overlay, intAttached.getValue());
ms.pop();
}
}
protected void renderItem(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, ItemStack stack) {
Minecraft.getInstance()
.getItemRenderer()
.renderItem(stack, TransformType.GROUND, light, overlay, ms, buffer);
}
protected float renderFluids(BasinTileEntity basin, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
@ -69,26 +132,7 @@ public class BasinRenderer extends SmartTileEntityRenderer<BasinTileEntity> {
SmartFluidTankBehaviour inputFluids = basin.getBehaviour(SmartFluidTankBehaviour.INPUT);
SmartFluidTankBehaviour outputFluids = basin.getBehaviour(SmartFluidTankBehaviour.OUTPUT);
SmartFluidTankBehaviour[] tanks = { inputFluids, outputFluids };
int renderedFluids = 0;
float totalUnits = 0;
for (SmartFluidTankBehaviour behaviour : tanks) {
if (behaviour == null)
continue;
for (TankSegment tankSegment : behaviour.getTanks()) {
if (tankSegment.getRenderedFluid()
.isEmpty())
continue;
float units = tankSegment.getTotalUnits(partialTicks);
if (units < 1)
continue;
totalUnits += units;
renderedFluids++;
}
}
if (renderedFluids == 0)
return 0;
float totalUnits = basin.getTotalFluidUnits();
if (totalUnits < 1)
return 0;
@ -111,8 +155,8 @@ public class BasinRenderer extends SmartTileEntityRenderer<BasinTileEntity> {
float units = tankSegment.getTotalUnits(partialTicks);
if (units < 1)
continue;
float partial = units / totalUnits;
float partial = MathHelper.clamp(units / totalUnits, 0, 1);
xMax += partial * 12 / 16f;
FluidRenderer.renderTiledFluidBB(renderedFluid, xMin, yMin, zMin, xMax, yMax, zMax, buffer, ms, light,
false);
@ -121,7 +165,7 @@ public class BasinRenderer extends SmartTileEntityRenderer<BasinTileEntity> {
}
}
return fluidLevel;
return yMax;
}
}

View file

@ -1,11 +1,18 @@
package com.simibubi.create.content.contraptions.processing;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import javax.annotation.Nonnull;
import com.simibubi.create.AllParticleTypes;
import com.simibubi.create.AllTags;
import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity;
import com.simibubi.create.content.contraptions.fluids.FluidFX;
import com.simibubi.create.content.contraptions.fluids.particle.FluidParticleData;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel;
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
@ -16,21 +23,32 @@ import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.IntAttached;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.LerpedFloat;
import com.simibubi.create.foundation.utility.LerpedFloat.Chaser;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.IParticleData;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
@ -44,25 +62,44 @@ import net.minecraftforge.items.wrapper.CombinedInvWrapper;
public class BasinTileEntity extends SmartTileEntity implements ITickableTileEntity {
private boolean areFluidsMoving;
LerpedFloat ingredientRotationSpeed;
LerpedFloat ingredientRotation;
public BasinInventory inputInventory;
public SmartFluidTankBehaviour inputTank;
protected SmartInventory outputInventory;
protected SmartFluidTankBehaviour outputTank;
private FilteringBehaviour filtering;
private boolean contentsChanged;
private Couple<SmartInventory> invs;
private Couple<SmartFluidTankBehaviour> tanks;
protected LazyOptional<IItemHandlerModifiable> itemCapability;
protected LazyOptional<IFluidHandler> fluidCapability;
private FilteringBehaviour filtering;
private boolean contentsChanged;
public static final int OUTPUT_ANIMATION_TIME = 10;
List<IntAttached<ItemStack>> visualizedOutputItems;
List<IntAttached<FluidStack>> visualizedOutputFluids;
public BasinTileEntity(TileEntityType<? extends BasinTileEntity> type) {
super(type);
inputInventory = new BasinInventory(9, this);
inputInventory.whenContentsChanged($ -> contentsChanged = true);
outputInventory = new BasinInventory(9, this).forbidInsertion();
areFluidsMoving = false;
itemCapability = LazyOptional.of(() -> new CombinedInvWrapper(inputInventory, outputInventory));
contentsChanged = true;
ingredientRotation = LerpedFloat.angular()
.startWithValue(0);
ingredientRotationSpeed = LerpedFloat.linear()
.startWithValue(0);
invs = Couple.create(inputInventory, outputInventory);
tanks = Couple.create(inputTank, outputTank);
visualizedOutputItems = Collections.synchronizedList(new ArrayList<>());
visualizedOutputFluids = Collections.synchronizedList(new ArrayList<>());
}
@Override
@ -78,6 +115,7 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
outputTank = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.OUTPUT, this, 2, 1000, true).forbidInsertion();
behaviours.add(inputTank);
behaviours.add(outputTank);
fluidCapability = LazyOptional.of(() -> {
LazyOptional<? extends IFluidHandler> inputCap = inputTank.getCapability();
LazyOptional<? extends IFluidHandler> outputCap = outputTank.getCapability();
@ -90,6 +128,15 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
super.read(compound, clientPacket);
inputInventory.deserializeNBT(compound.getCompound("InputItems"));
outputInventory.deserializeNBT(compound.getCompound("OutputItems"));
if (!clientPacket)
return;
NBTHelper.iterateCompoundList(compound.getList("VisualizedItems", NBT.TAG_COMPOUND),
c -> visualizedOutputItems.add(IntAttached.with(OUTPUT_ANIMATION_TIME, ItemStack.read(c))));
NBTHelper.iterateCompoundList(compound.getList("VisualizedFluids", NBT.TAG_COMPOUND),
c -> visualizedOutputFluids
.add(IntAttached.with(OUTPUT_ANIMATION_TIME, FluidStack.loadFluidStackFromNBT(c))));
}
@Override
@ -97,6 +144,16 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
super.write(compound, clientPacket);
compound.put("InputItems", inputInventory.serializeNBT());
compound.put("OutputItems", outputInventory.serializeNBT());
if (!clientPacket)
return;
compound.put("VisualizedItems", NBTHelper.writeCompoundList(visualizedOutputItems, ia -> ia.getValue()
.serializeNBT()));
compound.put("VisualizedFluids", NBTHelper.writeCompoundList(visualizedOutputFluids, ia -> ia.getValue()
.writeToNBT(new CompoundNBT())));
visualizedOutputItems.clear();
visualizedOutputFluids.clear();
}
public void onEmptied() {
@ -129,11 +186,26 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
@Override
public void lazyTick() {
super.lazyTick();
if (!world.isRemote)
return;
TileEntity tileEntity = world.getTileEntity(pos.up(2));
if (!(tileEntity instanceof MechanicalMixerTileEntity)) {
setAreFluidsMoving(false);
return;
}
MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) tileEntity;
setAreFluidsMoving(mixer.running && mixer.runningTicks <= 20);
}
@Override
public void tick() {
super.tick();
if (world.isRemote) {
createFluidParticles();
tickVisualizedOutputs();
ingredientRotationSpeed.tickChaser();
ingredientRotation.setValue(ingredientRotation.getValue() + ingredientRotationSpeed.getValue());
}
if (!contentsChanged)
return;
contentsChanged = false;
@ -143,7 +215,8 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
BlockPos toUpdate = pos.up()
.offset(offset);
BlockState stateToUpdate = world.getBlockState(toUpdate);
if (stateToUpdate.getBlock() instanceof BasinBlock && stateToUpdate.get(BasinBlock.FACING) == offset.getOpposite()) {
if (stateToUpdate.getBlock() instanceof BasinBlock
&& stateToUpdate.get(BasinBlock.FACING) == offset.getOpposite()) {
TileEntity te = world.getTileEntity(toUpdate);
if (te instanceof BasinTileEntity)
((BasinTileEntity) te).contentsChanged = true;
@ -151,6 +224,32 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
}
}
public float getTotalFluidUnits() {
int renderedFluids = 0;
float totalUnits = 0;
for (SmartFluidTankBehaviour behaviour : getTanks()) {
if (behaviour == null)
continue;
for (TankSegment tankSegment : behaviour.getTanks()) {
if (tankSegment.getRenderedFluid()
.isEmpty())
continue;
float units = tankSegment.getTotalUnits(0);
if (units < 1)
continue;
totalUnits += units;
renderedFluids++;
}
}
if (renderedFluids == 0)
return 0;
if (totalUnits < 1)
return 0;
return totalUnits;
}
private Optional<BasinOperatingTileEntity> getOperator() {
if (world == null)
return Optional.empty();
@ -224,6 +323,8 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), simulate)
.isEmpty())
return false;
else if (!simulate)
visualizedOutputItems.add(IntAttached.withZero(itemStack));
if (targetTank == null)
return false;
@ -231,10 +332,145 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
if (targetTank.fill(fluidStack.copy(), simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE) != fluidStack
.getAmount())
return false;
else if (!simulate)
visualizedOutputFluids.add(IntAttached.withZero(fluidStack));
return true;
}
public void readOnlyItems(CompoundNBT compound) {
inputInventory.deserializeNBT(compound.getCompound("InputItems"));
outputInventory.deserializeNBT(compound.getCompound("OutputItems"));
}
public static HeatLevel getHeatLevelOf(BlockState state) {
if (state.has(BlazeBurnerBlock.HEAT_LEVEL))
return state.get(BlazeBurnerBlock.HEAT_LEVEL);
return AllTags.AllBlockTags.FAN_HEATERS.matches(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE;
}
public Couple<SmartFluidTankBehaviour> getTanks() {
return tanks;
}
public Couple<SmartInventory> getInvs() {
return invs;
}
// client things
private void tickVisualizedOutputs() {
visualizedOutputFluids.forEach(IntAttached::decrement);
visualizedOutputItems.forEach(IntAttached::decrement);
visualizedOutputFluids.removeIf(IntAttached::isOrBelowZero);
visualizedOutputItems.removeIf(IntAttached::isOrBelowZero);
}
private void createFluidParticles() {
Random r = world.rand;
if (!visualizedOutputFluids.isEmpty())
createOutputFluidParticles(r);
if (!areFluidsMoving && r.nextFloat() > 1 / 8f)
return;
int segments = 0;
for (SmartFluidTankBehaviour behaviour : getTanks()) {
if (behaviour == null)
continue;
for (TankSegment tankSegment : behaviour.getTanks())
if (!tankSegment.isEmpty(0))
segments++;
}
if (segments < 2)
return;
float totalUnits = getTotalFluidUnits();
if (totalUnits == 0)
return;
float fluidLevel = MathHelper.clamp(totalUnits / 2000, 0, 1);
float rim = 2 / 16f;
float space = 12 / 16f;
float surface = pos.getY() + rim + space * fluidLevel + 1 / 32f;
if (areFluidsMoving) {
createMovingFluidParticles(surface, segments);
return;
}
for (SmartFluidTankBehaviour behaviour : getTanks()) {
if (behaviour == null)
continue;
for (TankSegment tankSegment : behaviour.getTanks()) {
if (tankSegment.isEmpty(0))
continue;
float x = pos.getX() + rim + space * r.nextFloat();
float z = pos.getZ() + rim + space * r.nextFloat();
world.addOptionalParticle(
new FluidParticleData(AllParticleTypes.BASIN_FLUID.get(), tankSegment.getRenderedFluid()), x,
surface, z, 0, 0, 0);
}
}
}
private void createOutputFluidParticles(Random r) {
BlockState blockState = getBlockState();
if (!(blockState.getBlock() instanceof BasinBlock))
return;
Direction direction = blockState.get(BasinBlock.FACING);
if (direction == Direction.DOWN)
return;
Vec3d directionVec = new Vec3d(direction.getDirectionVec());
Vec3d outVec = VecHelper.getCenterOf(pos)
.add(directionVec.scale(.65)
.subtract(0, 1 / 4f, 0));
Vec3d outMotion = directionVec.scale(1 / 16f)
.add(0, -1 / 16f, 0);
for (int i = 0; i < 3; i++) {
visualizedOutputFluids.forEach(ia -> {
FluidStack fluidStack = ia.getValue();
IParticleData fluidParticle = FluidFX.getFluidParticle(fluidStack);
Vec3d m = VecHelper.offsetRandomly(outMotion, r, 1 / 16f);
world.addOptionalParticle(fluidParticle, outVec.x, outVec.y, outVec.z, m.x, m.y, m.z);
});
}
}
private void createMovingFluidParticles(float surface, int segments) {
Vec3d pointer = new Vec3d(1, 0, 0).scale(1 / 16f);
float interval = 360f / segments;
Vec3d centerOf = VecHelper.getCenterOf(pos);
float intervalOffset = (AnimationTickHolder.ticks * 18) % 360;
int currentSegment = 0;
for (SmartFluidTankBehaviour behaviour : getTanks()) {
if (behaviour == null)
continue;
for (TankSegment tankSegment : behaviour.getTanks()) {
if (tankSegment.isEmpty(0))
continue;
float angle = interval * (1 + currentSegment) + intervalOffset;
Vec3d vec = centerOf.add(VecHelper.rotate(pointer, angle, Axis.Y));
world.addOptionalParticle(
new FluidParticleData(AllParticleTypes.BASIN_FLUID.get(), tankSegment.getRenderedFluid()),
vec.getX(), surface, vec.getZ(), 1, 0, 0);
currentSegment++;
}
}
}
public boolean areFluidsMoving() {
return areFluidsMoving;
}
public boolean setAreFluidsMoving(boolean areFluidsMoving) {
this.areFluidsMoving = areFluidsMoving;
ingredientRotationSpeed.chase(areFluidsMoving ? 20 : 0, .1f, Chaser.EXP);
return areFluidsMoving;
}
class BasinValueBox extends ValueBoxTransform.Sided {
@Override
@ -249,15 +485,4 @@ public class BasinTileEntity extends SmartTileEntity implements ITickableTileEnt
}
}
public void readOnlyItems(CompoundNBT compound) {
inputInventory.deserializeNBT(compound.getCompound("InputItems"));
outputInventory.deserializeNBT(compound.getCompound("OutputItems"));
}
public static HeatLevel getHeatLevelOf(BlockState state) {
if (state.has(BlazeBurnerBlock.HEAT_LEVEL))
return state.get(BlazeBurnerBlock.HEAT_LEVEL);
return AllTags.AllBlockTags.FAN_HEATERS.matches(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE;
}
}

View file

@ -267,6 +267,16 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour {
.isEmpty())
renderedFluid = tank.getFluid();
}
public boolean isEmpty(float partialTicks) {
FluidStack renderedFluid = getRenderedFluid();
if (renderedFluid.isEmpty())
return true;
float units = getTotalUnits(partialTicks);
if (units < 1)
return true;
return false;
}
}

View file

@ -1,5 +1,6 @@
package com.simibubi.create.foundation.utility;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
@ -12,7 +13,7 @@ import com.google.common.collect.ImmutableList;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
public class Couple<T> extends Pair<T, T> {
public class Couple<T> extends Pair<T, T> implements Iterable<T> {
private static Couple<Boolean> TRUE_AND_FALSE = Couple.create(true, false);
@ -62,7 +63,8 @@ public class Couple<T> extends Pair<T, T> {
setSecond(function.apply(getSecond(), values.getSecond()));
}
public void forEach(Consumer<T> consumer) {
@Override
public void forEach(Consumer<? super T> consumer) {
consumer.accept(getFirst());
consumer.accept(getSecond());
}
@ -89,4 +91,36 @@ public class Couple<T> extends Pair<T, T> {
return new Couple<>(readCompoundList.get(0), readCompoundList.get(1));
}
@Override
public Iterator<T> iterator() {
return new Couplerator<>(this);
}
private static class Couplerator<T> implements Iterator<T> {
int state;
private Couple<T> couple;
public Couplerator(Couple<T> couple) {
this.couple = couple;
state = 0;
}
@Override
public boolean hasNext() {
return state != 2;
}
@Override
public T next() {
state++;
if (state == 1)
return couple.first;
if (state == 2)
return couple.second;
return null;
}
}
}

View file

@ -0,0 +1,37 @@
package com.simibubi.create.foundation.utility;
public class IntAttached<V> extends Pair<Integer, V> {
protected IntAttached(Integer first, V second) {
super(first, second);
}
public static <V> IntAttached<V> with(int number, V value) {
return new IntAttached<>(number, value);
}
public static <V> IntAttached<V> withZero(V value) {
return new IntAttached<>(0, value);
}
public boolean isZero() {
return first.intValue() == 0;
}
public boolean isOrBelowZero() {
return first.intValue() <= 0;
}
public void increment() {
first++;
}
public void decrement() {
first--;
}
public V getValue() {
return getSecond();
}
}

View file

@ -123,23 +123,10 @@
"up": {"uv": [6, 0, 8, 6], "rotation": 90, "texture": "#3"}
}
},
{
"name": "BackBottom",
"from": [3.9, -2, 18],
"to": [12.1, 2, 26],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, -4, 17]},
"faces": {
"east": {"uv": [12, 12, 14, 16], "rotation": 270, "texture": "#7"},
"south": {"uv": [8, 13, 12, 15], "rotation": 180, "texture": "#7"},
"west": {"uv": [12, 12, 14, 16], "rotation": 270, "texture": "#7"},
"up": {"uv": [8, 12, 12, 16], "rotation": 180, "texture": "#7"},
"down": {"uv": [8, 12, 12, 16], "rotation": 180, "texture": "#7"}
}
},
{
"name": "Back",
"from": [2.1, -2.1, 14],
"to": [13.9, 13.9, 17.9],
"to": [13.9, 13.95, 18.1],
"rotation": {"angle": 0, "axis": "y", "origin": [8, -8, 6]},
"faces": {
"north": {"uv": [0, 4, 16, 16], "rotation": 90, "texture": "#5"},
@ -204,7 +191,7 @@
{
"name": "Base",
"origin": [9, -4, 8],
"children": [9, 10, 11, 12, 13]
"children": [9, 10, 11, 12]
}
]
}

View file

@ -108,23 +108,10 @@
"down": {"uv": [0, 0, 1, 6], "texture": "#particle"}
}
},
{
"name": "BackBottom",
"from": [3.9, -2, 18],
"to": [12.1, 2, 26],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, -4, 17]},
"faces": {
"east": {"uv": [12, 12, 14, 16], "rotation": 270, "texture": "#7"},
"south": {"uv": [8, 13, 12, 15], "rotation": 180, "texture": "#7"},
"west": {"uv": [12, 12, 14, 16], "rotation": 270, "texture": "#7"},
"up": {"uv": [8, 12, 12, 16], "rotation": 180, "texture": "#7"},
"down": {"uv": [8, 12, 12, 16], "rotation": 180, "texture": "#7"}
}
},
{
"name": "Back",
"from": [2.1, -2.1, 14],
"to": [13.9, 13.9, 17.9],
"to": [13.9, 13.95, 18.1],
"rotation": {"angle": 0, "axis": "y", "origin": [8, -8.1, 6]},
"faces": {
"east": {"uv": [0, 0, 16, 4], "rotation": 90, "texture": "#5"},
@ -196,8 +183,8 @@
{
"name": "Base",
"origin": [9, -4, 8],
"children": [8, 9, 10, 11, 12]
"children": [8, 9, 10, 11]
}
]
}, 13]
}, 12]
}

View file

@ -3,11 +3,10 @@
"parent": "create:block/large_wheels",
"textures": {
"6": "create:block/crushing_wheel_body",
"spruce_log_top": "block/spruce_log",
"spruce_log_top": "create:block/smooth_dark_log_top",
"axis_top": "create:block/axis_top",
"axis": "create:block/axis",
"crushing_wheel": "create:block/crushing_wheel",
"spruce_log": "block/spruce_log",
"particle": "block/polished_andesite"
},
"elements": [
@ -27,68 +26,69 @@
},
{
"name": "B1",
"from": [2, 2, -8],
"to": [9, 14, 7],
"rotation": {"angle": -22.5, "axis": "y", "origin": [8, 8, 8]},
"from": [2, 1.95, -8],
"to": [9, 14.05, 7],
"rotation": {"angle": -22.5, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [7.5, 6, 11, 12], "texture": "#6"},
"east": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"south": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"west": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"west": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"up": {"uv": [0, 9.5, 7.5, 13], "rotation": 270, "texture": "#6"},
"down": {"uv": [0, 9.5, 7.5, 13], "rotation": 90, "texture": "#6"}
}
},
{
"name": "B2",
"from": [2, 2.1, -8],
"to": [10, 13.9, 7],
"from": [2, 1.9, -8],
"to": [10, 14.1, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"north": {"uv": [3.5, 0, 7.5, 6], "texture": "#6"},
"east": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"south": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"west": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"up": {"uv": [0, 6, 7.5, 9.5], "rotation": 270, "texture": "#6"},
"west": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"up": {"uv": [0, 6.5, 7.5, 10.5], "rotation": 270, "texture": "#6"},
"down": {"uv": [0, 6, 7.5, 9.5], "rotation": 90, "texture": "#6"}
}
},
{
"name": "B3",
"from": [2, 2, -8],
"to": [9, 14, 7],
"rotation": {"angle": 22.5, "axis": "y", "origin": [8, 8, 8]},
"from": [2, 1.95, -8],
"to": [9, 14.05, 7],
"rotation": {"angle": 22.5, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [11, 0, 14.5, 6], "texture": "#6"},
"east": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"south": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"west": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"west": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"up": {"uv": [0, 6, 7.5, 9.5], "rotation": 270, "texture": "#6"},
"down": {"uv": [0, 6, 7.5, 9.5], "rotation": 90, "texture": "#6"}
}
},
{
"name": "B4",
"from": [2, 2.1, -8],
"to": [10, 13.9, 7],
"rotation": {"angle": 45, "axis": "y", "origin": [8, 8, 8]},
"from": [2, 1.9, -8],
"to": [10, 14.1, 7],
"rotation": {"angle": 45, "axis": "y", "origin": [8, 8.05, 8]},
"faces": {
"north": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"north": {"uv": [3.5, 0, 7.5, 6], "texture": "#6"},
"east": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"south": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"west": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"up": {"uv": [8.5, 12.5, 16, 16], "rotation": 270, "texture": "#6"},
"west": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"up": {"uv": [0, 6.5, 7.5, 10.5], "rotation": 270, "texture": "#6"},
"down": {"uv": [8.5, 12.5, 16, 16], "rotation": 90, "texture": "#6"}
}
},
{
"name": "B5",
"from": [-8, 2, 7],
"to": [7, 14, 14],
"rotation": {"angle": -22.5, "axis": "y", "origin": [8, 8, 8]},
"from": [-8, 1.95, 7],
"to": [7, 14.05, 14],
"rotation": {"angle": -22.5, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"east": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"south": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"south": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"west": {"uv": [7.5, 6, 11, 12], "texture": "#6"},
"up": {"uv": [0, 9.5, 7.5, 13], "rotation": 180, "texture": "#6"},
"down": {"uv": [0, 9.5, 7.5, 13], "rotation": 180, "texture": "#6"}
@ -96,26 +96,27 @@
},
{
"name": "B6",
"from": [-8, 2.1, 6],
"to": [7, 13.9, 14],
"from": [-8, 1.9, 6],
"to": [7, 14.1, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"east": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"south": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"west": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"up": {"uv": [0, 6, 7.5, 9.5], "rotation": 180, "texture": "#6"},
"south": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"west": {"uv": [3.5, 0, 7.5, 6], "texture": "#6"},
"up": {"uv": [0, 6.5, 7.5, 10.5], "rotation": 180, "texture": "#6"},
"down": {"uv": [0, 6, 7.5, 9.5], "rotation": 180, "texture": "#6"}
}
},
{
"name": "B7",
"from": [-8, 2, 7],
"to": [7, 14, 14],
"rotation": {"angle": 22.5, "axis": "y", "origin": [8, 8, 8]},
"from": [-8, 1.95, 7],
"to": [7, 14.05, 14],
"rotation": {"angle": 22.5, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"east": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"south": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"south": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"west": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"up": {"uv": [0, 6, 7.5, 9.5], "rotation": 180, "texture": "#6"},
"down": {"uv": [0, 6, 7.5, 9.5], "rotation": 180, "texture": "#6"}
@ -123,26 +124,26 @@
},
{
"name": "B8",
"from": [-8, 2.1, 6],
"to": [7, 13.9, 14],
"rotation": {"angle": 45, "axis": "y", "origin": [8, 8, 8]},
"from": [-8, 1.9, 6],
"to": [7, 14.1, 14],
"rotation": {"angle": 45, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"east": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"south": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"west": {"uv": [11, 0, 14.5, 6], "texture": "#6"},
"up": {"uv": [8.5, 12.5, 16, 16], "rotation": 180, "texture": "#6"},
"south": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"west": {"uv": [3.5, 0, 7.5, 6], "texture": "#6"},
"up": {"uv": [0, 6.5, 7.5, 10.5], "rotation": 180, "texture": "#6"},
"down": {"uv": [8.5, 12.5, 16, 16], "rotation": 180, "texture": "#6"}
}
},
{
"name": "B9",
"from": [7, 2, 9],
"to": [14, 14, 24],
"rotation": {"angle": -22.5, "axis": "y", "origin": [8, 8, 8]},
"from": [7, 1.95, 9],
"to": [14, 14.05, 24],
"rotation": {"angle": -22.5, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"east": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"east": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"south": {"uv": [7.5, 6, 11, 12], "texture": "#6"},
"west": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"up": {"uv": [0, 9.5, 7.5, 13], "rotation": 90, "texture": "#6"},
@ -151,26 +152,27 @@
},
{
"name": "B10",
"from": [6, 2.1, 9],
"to": [14, 13.9, 24],
"from": [6, 1.9, 9],
"to": [14, 14.1, 24],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"east": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"south": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"east": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"south": {"uv": [3.5, 0, 7.5, 6], "texture": "#6"},
"west": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"up": {"uv": [0, 6, 7.5, 9.5], "rotation": 90, "texture": "#6"},
"up": {"uv": [0, 6, 7.5, 10], "rotation": 90, "texture": "#6"},
"down": {"uv": [0, 6, 7.5, 9.5], "rotation": 270, "texture": "#6"}
}
},
{
"name": "B11",
"from": [7, 2, 9],
"to": [14, 14, 24],
"rotation": {"angle": 22.5, "axis": "y", "origin": [8, 8, 8]},
"from": [7, 1.95, 9],
"to": [14, 14.05, 24],
"rotation": {"angle": 22.5, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"east": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"south": {"uv": [11, 0, 14.5, 6], "texture": "#6"},
"east": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"south": {"uv": [7.5, 6, 11, 12], "texture": "#6"},
"west": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"up": {"uv": [8.5, 12.5, 16, 16], "rotation": 90, "texture": "#6"},
"down": {"uv": [8.5, 12.5, 16, 16], "rotation": 270, "texture": "#6"}
@ -178,25 +180,25 @@
},
{
"name": "B12",
"from": [6, 2.1, 9],
"to": [14, 13.9, 24],
"rotation": {"angle": 45, "axis": "y", "origin": [8, 8, 8]},
"from": [6, 1.9, 9],
"to": [14, 14.1, 24],
"rotation": {"angle": 45, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"east": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"south": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"east": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"south": {"uv": [3.5, 0, 7.5, 6], "texture": "#6"},
"west": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"up": {"uv": [0, 6, 7.5, 9.5], "rotation": 90, "texture": "#6"},
"up": {"uv": [0, 6.5, 7.5, 10.5], "rotation": 90, "texture": "#6"},
"down": {"uv": [0, 6, 7.5, 9.5], "rotation": 270, "texture": "#6"}
}
},
{
"name": "B13",
"from": [9, 2, 2],
"to": [24, 14, 9],
"rotation": {"angle": -22.5, "axis": "y", "origin": [8, 8, 8]},
"from": [9, 1.95, 2],
"to": [24, 14.05, 9],
"rotation": {"angle": -22.5, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"north": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"east": {"uv": [7.5, 6, 11, 12], "texture": "#6"},
"south": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"west": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
@ -206,24 +208,25 @@
},
{
"name": "B14",
"from": [9, 2.1, 2],
"to": [24, 13.9, 10],
"from": [9, 1.9, 2],
"to": [24, 14.1, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"east": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"north": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"east": {"uv": [3.5, 0, 7.5, 6], "texture": "#6"},
"south": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"west": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"up": {"uv": [0, 6, 7.5, 9.5], "texture": "#6"},
"up": {"uv": [0, 7.5, 7.5, 11.5], "texture": "#6"},
"down": {"uv": [0, 6, 7.5, 9.5], "texture": "#6"}
}
},
{
"name": "B15",
"from": [9, 2, 2],
"to": [24, 14, 9],
"rotation": {"angle": 22.5, "axis": "y", "origin": [8, 8, 8]},
"from": [9, 1.95, 2],
"to": [24, 14.05, 9],
"rotation": {"angle": 22.5, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"north": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"east": {"uv": [11, 0, 14.5, 6], "texture": "#6"},
"south": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"west": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
@ -233,15 +236,15 @@
},
{
"name": "B16",
"from": [2, 2.1, -8],
"to": [10, 13.9, 7],
"rotation": {"angle": -45, "axis": "y", "origin": [8, 8, 8]},
"from": [2, 1.9, -8],
"to": [10, 14.1, 7],
"rotation": {"angle": -45, "axis": "y", "origin": [8, 7.95, 8]},
"faces": {
"north": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"north": {"uv": [3.5, 0, 7.5, 6], "texture": "#6"},
"east": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"south": {"uv": [7.5, 0, 11, 6], "texture": "#6"},
"west": {"uv": [0, 0, 7.5, 6], "texture": "#6"},
"up": {"uv": [0, 6, 7.5, 9.5], "rotation": 270, "texture": "#6"},
"west": {"uv": [1.5, 6, 7.5, 0], "rotation": 180, "texture": "#6"},
"up": {"uv": [0, 6.5, 7.5, 10.5], "rotation": 270, "texture": "#6"},
"down": {"uv": [0, 6, 7.5, 9.5], "rotation": 90, "texture": "#6"}
}
},
@ -251,18 +254,18 @@
"to": [12, 15, 12],
"shade": false,
"faces": {
"north": {"uv": [4, 1, 12, 15], "texture": "#spruce_log"},
"east": {"uv": [4, 1, 12, 15], "texture": "#spruce_log"},
"south": {"uv": [4, 1, 12, 15], "texture": "#spruce_log"},
"west": {"uv": [4, 1, 12, 15], "texture": "#spruce_log"},
"north": {"uv": [4, 1, 12, 15], "texture": "#spruce_log_top"},
"east": {"uv": [4, 1, 12, 15], "texture": "#spruce_log_top"},
"south": {"uv": [4, 1, 12, 15], "texture": "#spruce_log_top"},
"west": {"uv": [4, 1, 12, 15], "texture": "#spruce_log_top"},
"up": {"uv": [4, 4, 12, 12], "texture": "#spruce_log_top"},
"down": {"uv": [4, 4, 12, 12], "texture": "#spruce_log_top"}
}
},
{
"name": "Cover",
"from": [-4, 1.9, -4],
"to": [20, 14.1, 20],
"from": [-4, 1.85, -4],
"to": [20, 14.15, 20],
"faces": {
"up": {"uv": [2, 2, 14, 14], "texture": "#crushing_wheel"},
"down": {"uv": [2, 2, 14, 14], "texture": "#crushing_wheel"}
@ -276,4 +279,4 @@
"children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
}
]
}
}

View file

@ -0,0 +1 @@
{}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 826 B