Merge branch 'mc1.15/dev' into mc1.16/dev

This commit is contained in:
simibubi 2020-10-30 19:36:03 +01:00
commit d26139576c
28 changed files with 1016 additions and 242 deletions

View file

@ -1639,6 +1639,7 @@ c023b9221d7983487d21e5ecc7d92246cfc7e791 data/create/advancements/recipes/create
9af3d92d11c3f520df3e22f3069042bf34585010 data/create/advancements/recipes/create.base/crafting/kinetics/green_valve_handle_from_other_valve_handle.json
dbb96a4db4ef8172af73a626bed9727278d804bd data/create/advancements/recipes/create.base/crafting/kinetics/hand_crank.json
21cd686e1f3a4004d8e9bd3d92675bd61fb2b4db data/create/advancements/recipes/create.base/crafting/kinetics/hose_pulley.json
58450edb1767e9d56256186acba954ca09481548 data/create/advancements/recipes/create.base/crafting/kinetics/item_drain.json
a71b626b6ee58a4eabee56f67c48f041a1323506 data/create/advancements/recipes/create.base/crafting/kinetics/large_cogwheel.json
eb007bb079bbe6b6aaad2ca90f5af84261e3f8ea data/create/advancements/recipes/create.base/crafting/kinetics/light_blue_seat.json
571da50fbf5f2fcd3363b3dab91e7233e0ebffa0 data/create/advancements/recipes/create.base/crafting/kinetics/light_blue_seat_from_other_seat.json
@ -2626,7 +2627,7 @@ ad1c3ce1e98b8483512bdd754f2e5930c7b3ae85 data/create/recipes/crafting/kinetics/d
be86df1c4d7af14bc5dcfe044d07c03b6c6d2a75 data/create/recipes/crafting/kinetics/depot.json
9c5d30f25a130d591b924c50e5c83e3b787c2758 data/create/recipes/crafting/kinetics/empty_blaze_burner.json
860f9c4aa677d2354bcf5fe3e6d28cc7cf56dd06 data/create/recipes/crafting/kinetics/encased_belt.json
e416a453316cc6a2f68795b0ab9c91a842d72510 data/create/recipes/crafting/kinetics/encased_fan.json
b07496e4ba5bc56a2c5a395b612c68ba21328867 data/create/recipes/crafting/kinetics/encased_fan.json
0dd0cc11eaa6789fc612af3231ed247893852178 data/create/recipes/crafting/kinetics/filter.json
30ae02825e54c0cc07be8f4decf9d432e7d61ba2 data/create/recipes/crafting/kinetics/fluid_pipe.json
86ad4d2820e8e2b01de8d977af7796119dfb7430 data/create/recipes/crafting/kinetics/fluid_tank.json
@ -2644,6 +2645,7 @@ b7fa20d10c0e0e7270b1c0d6f3881b8e25b39bea data/create/recipes/crafting/kinetics/g
63edaccace961a65aa7bd406d36894c7ca4816b8 data/create/recipes/crafting/kinetics/green_valve_handle_from_other_valve_handle.json
9f08bdaeec88e04a43c2dc103869f9648deee079 data/create/recipes/crafting/kinetics/hand_crank.json
d10639b0c3999481531fe0a9383a1bb4af60225e data/create/recipes/crafting/kinetics/hose_pulley.json
f4fbb11ef55f3431bd387f3f6f258513bfbc8011 data/create/recipes/crafting/kinetics/item_drain.json
237541c1c318b8426734c1c43be31fbd01413d39 data/create/recipes/crafting/kinetics/large_cogwheel.json
a33e3301fc6d3a446e61a1c4b8a93aff079baeba data/create/recipes/crafting/kinetics/light_blue_seat.json
958bb5d3aeb8d8e5dbf5d97cf5fd9ff5151575dc data/create/recipes/crafting/kinetics/light_blue_seat_from_other_seat.json

View file

@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"create:crafting/kinetics/item_drain"
]
},
"criteria": {
"has_item": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"item": "create:copper_casing"
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "create:crafting/kinetics/item_drain"
}
}
},
"requirements": [
[
"has_item",
"has_the_recipe"
]
]
}

View file

@ -3,20 +3,17 @@
"pattern": [
" S ",
"RAR",
"BPB"
" P "
],
"key": {
"S": {
"item": "create:shaft"
},
"A": {
"item": "create:andesite_alloy"
"item": "create:andesite_casing"
},
"R": {
"tag": "minecraft:planks"
},
"B": {
"item": "minecraft:iron_bars"
"item": "create:cogwheel"
},
"P": {
"item": "create:propeller"

View file

@ -0,0 +1,18 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"P",
"S"
],
"key": {
"P": {
"item": "minecraft:iron_bars"
},
"S": {
"item": "create:copper_casing"
}
},
"result": {
"item": "create:item_drain"
}
}

View file

@ -545,7 +545,7 @@ public class AllBlocks {
.patternLine("-")
.key('#', DyeHelper.getTagOfDye(colour))
.key('-', AllItemTags.VALVE_HANDLES.tag)
.addCriterion("has_valve", p.hasItem(AllItemTags.VALVE_HANDLES.tag))
.addCriterion("has_valve", RegistrateRecipeProvider.hasItem(AllItemTags.VALVE_HANDLES.tag))
.build(p, Create.asResource("crafting/kinetics/" + c.getName() + "_from_other_valve_handle")))
.register();
}
@ -555,8 +555,7 @@ public class AllBlocks {
.initialProperties(SharedProperties::softMetal)
.properties(AbstractBlock.Properties::nonOpaque)
.blockstate(new FluidTankGenerator()::generate)
.onRegister(CreateRegistrate
.blockModel(() -> m -> new FluidTankModel(m, AllSpriteShifts.FLUID_TANK, AllSpriteShifts.COPPER_CASING)))
.onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::standard))
.addLayer(() -> RenderType::getCutoutMipped)
.item(FluidTankItem::new)
.model(AssetLookup.<FluidTankItem>customItemModel("_", "block_single_window"))
@ -568,8 +567,7 @@ public class AllBlocks {
.initialProperties(SharedProperties::softMetal)
.properties(Block.Properties::nonOpaque)
.blockstate(new FluidTankGenerator("creative_")::generate)
.onRegister(CreateRegistrate.blockModel(
() -> m -> new FluidTankModel(m, AllSpriteShifts.CREATIVE_FLUID_TANK, AllSpriteShifts.CREATIVE_CASING)))
.onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::creative))
.addLayer(() -> RenderType::getCutoutMipped)
.item(FluidTankItem::new)
.model((c, p) -> p.withExistingParent(c.getName(), p.modLoc("block/fluid_tank/block_single_window"))
@ -787,42 +785,45 @@ public class AllBlocks {
.simpleItem()
.register();
public static final BlockEntry<?>[] SEATS = new BlockEntry<?>[DyeColor.values().length];
static {
// SEATS
for (DyeColor colour : DyeColor.values()) {
String colourName = colour.getString();
SeatMovementBehaviour movementBehaviour = new SeatMovementBehaviour();
REGISTRATE.block(colourName + "_seat", p -> new SeatBlock(p, colour == DyeColor.RED))
.initialProperties(SharedProperties::wooden)
.onRegister(addMovementBehaviour(movementBehaviour))
.blockstate((c, p) -> {
p.simpleBlock(c.get(), p.models()
.withExistingParent(colourName + "_seat", p.modLoc("block/seat"))
.texture("1", p.modLoc("block/seat/top_" + colourName))
.texture("2", p.modLoc("block/seat/side_" + colourName)));
})
.recipe((c, p) -> {
ShapedRecipeBuilder.shapedRecipe(c.get())
.patternLine("#")
.patternLine("-")
.key('#', DyeHelper.getWoolOfDye(colour))
.key('-', ItemTags.WOODEN_SLABS)
.addCriterion("has_wool", RegistrateRecipeProvider.hasItem(ItemTags.WOOL))
.build(p, Create.asResource("crafting/kinetics/" + c.getName()));
ShapedRecipeBuilder.shapedRecipe(c.get())
.patternLine("#")
.patternLine("-")
.key('#', DyeHelper.getTagOfDye(colour))
.key('-', AllItemTags.SEATS.tag)
.addCriterion("has_seat", RegistrateRecipeProvider.hasItem(AllItemTags.SEATS.tag))
.build(p, Create.asResource("crafting/kinetics/" + c.getName() + "_from_other_seat"));
})
.onRegisterAfter(Item.class, v -> TooltipHelper.referTo(v, "block.create.seat"))
.tag(AllBlockTags.SEATS.tag)
.item()
.tag(AllItemTags.SEATS.tag)
.build()
.register();
SEATS[colour.ordinal()] =
REGISTRATE.block(colourName + "_seat", p -> new SeatBlock(p, colour == DyeColor.RED))
.initialProperties(SharedProperties::wooden)
.onRegister(addMovementBehaviour(movementBehaviour))
.blockstate((c, p) -> {
p.simpleBlock(c.get(), p.models()
.withExistingParent(colourName + "_seat", p.modLoc("block/seat"))
.texture("1", p.modLoc("block/seat/top_" + colourName))
.texture("2", p.modLoc("block/seat/side_" + colourName)));
})
.recipe((c, p) -> {
ShapedRecipeBuilder.shapedRecipe(c.get())
.patternLine("#")
.patternLine("-")
.key('#', DyeHelper.getWoolOfDye(colour))
.key('-', ItemTags.WOODEN_SLABS)
.addCriterion("has_wool", RegistrateRecipeProvider.hasItem(ItemTags.WOOL))
.build(p, Create.asResource("crafting/kinetics/" + c.getName()));
ShapedRecipeBuilder.shapedRecipe(c.get())
.patternLine("#")
.patternLine("-")
.key('#', DyeHelper.getTagOfDye(colour))
.key('-', AllItemTags.SEATS.tag)
.addCriterion("has_seat", RegistrateRecipeProvider.hasItem(AllItemTags.SEATS.tag))
.build(p, Create.asResource("crafting/kinetics/" + c.getName() + "_from_other_seat"));
})
.onRegisterAfter(Item.class, v -> TooltipHelper.referTo(v, "block.create.seat"))
.tag(AllBlockTags.SEATS.tag)
.item()
.tag(AllItemTags.SEATS.tag)
.build()
.register();
}
}
@ -1166,14 +1167,13 @@ public class AllBlocks {
.build()
.register();
public static final BlockEntry<Block> BRASS_BLOCK =
REGISTRATE.block("brass_block", p -> new Block(p))
.initialProperties(() -> Blocks.IRON_BLOCK)
.tag(Tags.Blocks.STORAGE_BLOCKS)
.transform(tagBlockAndItem("storage_blocks/brass"))
.tag(Tags.Items.STORAGE_BLOCKS)
.build()
.register();
public static final BlockEntry<Block> BRASS_BLOCK = REGISTRATE.block("brass_block", p -> new Block(p))
.initialProperties(() -> Blocks.IRON_BLOCK)
.tag(Tags.Blocks.STORAGE_BLOCKS)
.transform(tagBlockAndItem("storage_blocks/brass"))
.tag(Tags.Items.STORAGE_BLOCKS)
.build()
.register();
// Load this class

View file

@ -50,6 +50,8 @@ import com.simibubi.create.content.contraptions.fluids.PumpRenderer;
import com.simibubi.create.content.contraptions.fluids.PumpTileEntity;
import com.simibubi.create.content.contraptions.fluids.actors.HosePulleyRenderer;
import com.simibubi.create.content.contraptions.fluids.actors.HosePulleyTileEntity;
import com.simibubi.create.content.contraptions.fluids.actors.ItemDrainRenderer;
import com.simibubi.create.content.contraptions.fluids.actors.ItemDrainTileEntity;
import com.simibubi.create.content.contraptions.fluids.actors.SpoutRenderer;
import com.simibubi.create.content.contraptions.fluids.actors.SpoutTileEntity;
import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeTileEntity;
@ -257,6 +259,12 @@ public class AllTileEntities {
.renderer(() -> SpoutRenderer::new)
.register();
public static final TileEntityEntry<ItemDrainTileEntity> ITEM_DRAIN = Create.registrate()
.tileEntity("item_drain", ItemDrainTileEntity::new)
.validBlocks(AllBlocks.ITEM_DRAIN)
.renderer(() -> ItemDrainRenderer::new)
.register();
public static final TileEntityEntry<BeltTileEntity> BELT = Create.registrate()
.tileEntity("belt", BeltTileEntity::new)
.validBlocks(AllBlocks.BELT)

View file

@ -9,8 +9,10 @@ import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlock;
import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerTileEntity;
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
import com.simibubi.create.content.contraptions.relays.encased.DirectionalShaftHalvesTileEntity;
import com.simibubi.create.content.contraptions.relays.encased.EncasedBeltBlock;
import com.simibubi.create.content.contraptions.relays.encased.SplitShaftTileEntity;
@ -123,13 +125,13 @@ public class RotationPropagator {
private static float getConveyedSpeed(KineticTileEntity from, KineticTileEntity to) {
final BlockState stateFrom = from.getBlockState();
final BlockState stateTo = to.getBlockState();
final BlockPos diff = to.getPos()
.subtract(from.getPos());
// Rotation Speed Controller <-> Large Gear
if (isLargeCogToSpeedController(stateFrom, stateTo, diff))
if (isLargeCogToSpeedController(stateFrom, stateTo, to.getPos()
.subtract(from.getPos())))
return SpeedControllerTileEntity.getConveyedSpeed(from, to, true);
if (isLargeCogToSpeedController(stateTo, stateFrom, diff))
if (isLargeCogToSpeedController(stateTo, stateFrom, from.getPos()
.subtract(to.getPos())))
return SpeedControllerTileEntity.getConveyedSpeed(to, from, false);
float rotationSpeedModifier = getRotationSpeedModifier(from, to);
@ -188,7 +190,12 @@ public class RotationPropagator {
private static boolean isLargeCogToSpeedController(BlockState from, BlockState to, BlockPos diff) {
if (!isLargeCog(from) || !AllBlocks.ROTATION_SPEED_CONTROLLER.has(to))
return false;
if (!diff.equals(BlockPos.ZERO.up()) && !diff.equals(BlockPos.ZERO.down()))
if (!diff.equals(BlockPos.ZERO.down()))
return false;
Axis axis = from.get(CogWheelBlock.AXIS);
if (axis.isVertical())
return false;
if (to.get(SpeedControllerBlock.HORIZONTAL_AXIS) == axis)
return false;
return true;
}
@ -395,12 +402,12 @@ public class RotationPropagator {
public static boolean isConnected(KineticTileEntity from, KineticTileEntity to) {
final BlockState stateFrom = from.getBlockState();
final BlockState stateTo = to.getBlockState();
final BlockPos diff = to.getPos()
.subtract(from.getPos());
if (isLargeCogToSpeedController(stateFrom, stateTo, diff))
if (isLargeCogToSpeedController(stateFrom, stateTo, to.getPos()
.subtract(from.getPos())))
return true;
if (isLargeCogToSpeedController(stateTo, stateFrom, diff))
if (isLargeCogToSpeedController(stateTo, stateFrom, from.getPos()
.subtract(to.getPos())))
return true;
return getRotationSpeedModifier(from, to) != 0;
}

View file

@ -5,7 +5,9 @@ import java.util.List;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.foundation.utility.DyeHelper;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block;
@ -16,6 +18,7 @@ import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MobEntity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.DyeColor;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.pathfinding.PathNodeType;
@ -85,11 +88,25 @@ public class SeatBlock extends Block {
}
@Override
public ActionResultType onUse(BlockState p_225533_1_, World world, BlockPos pos, PlayerEntity player,
Hand p_225533_5_, BlockRayTraceResult p_225533_6_) {
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
BlockRayTraceResult p_225533_6_) {
if (player.isSneaking())
return ActionResultType.PASS;
ItemStack heldItem = player.getHeldItem(hand);
for (DyeColor color : DyeColor.values()) {
if (!heldItem.getItem()
.isIn(DyeHelper.getTagOfDye(color)))
continue;
if (world.isRemote)
return ActionResultType.SUCCESS;
BlockState newState = AllBlocks.SEATS[color.ordinal()].getDefaultState();
if (newState != state)
world.setBlockState(pos, newState);
return ActionResultType.SUCCESS;
}
List<SeatEntity> seats = world.getEntitiesWithinAABB(SeatEntity.class, new AxisAlignedBB(pos));
if (!seats.isEmpty()) {
SeatEntity seatEntity = seats.get(0);

View file

@ -3,10 +3,20 @@ package com.simibubi.create.content.contraptions.components.crank;
import javax.annotation.ParametersAreNonnullByDefault;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.DyeHelper;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.DyeColor;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@ -17,29 +27,50 @@ public class ValveHandleBlock extends HandCrankBlock {
public static ValveHandleBlock copper(Properties properties) {
return new ValveHandleBlock(properties, true);
}
public static ValveHandleBlock dyed(Properties properties) {
return new ValveHandleBlock(properties, false);
}
private ValveHandleBlock(Properties properties, boolean inCreativeTab) {
super(properties);
this.inCreativeTab = inCreativeTab;
}
@Override
public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
ItemStack heldItem = player.getHeldItem(handIn);
for (DyeColor color : DyeColor.values()) {
if (!heldItem.getItem()
.isIn(DyeHelper.getTagOfDye(color)))
continue;
if (worldIn.isRemote)
return ActionResultType.SUCCESS;
BlockState newState = AllBlocks.DYED_VALVE_HANDLES[color.ordinal()].getDefaultState()
.with(FACING, state.get(FACING));
if (newState != state)
worldIn.setBlockState(pos, newState);
return ActionResultType.SUCCESS;
}
return super.onUse(state, worldIn, pos, player, handIn, hit);
}
@Override
public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> p_149666_2_) {
if (group != ItemGroup.SEARCH && !inCreativeTab)
return;
super.fillItemGroup(group, p_149666_2_);
}
@Override
@OnlyIn(Dist.CLIENT)
public AllBlockPartials getRenderedHandle() {
return null;
}
@Override
public int getRotationSpeed() {
return 16;

View file

@ -5,6 +5,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
@ -20,6 +22,7 @@ import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.DyeColor;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ShearsItem;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
@ -80,6 +83,12 @@ public class SailBlock extends ProperDirectionalBlock {
return ActionResultType.SUCCESS;
}
if (heldItem.getItem() instanceof ShearsItem) {
if (!world.isRemote)
applyDye(state, world, pos, null);
return ActionResultType.SUCCESS;
}
if (frame)
return ActionResultType.PASS;
@ -95,9 +104,10 @@ public class SailBlock extends ProperDirectionalBlock {
return ActionResultType.PASS;
}
protected void applyDye(BlockState state, World world, BlockPos pos, DyeColor color) {
BlockState newState = AllBlocks.DYED_SAILS[color.ordinal()].getDefaultState()
.with(FACING, state.get(FACING));
protected void applyDye(BlockState state, World world, BlockPos pos, @Nullable DyeColor color) {
BlockState newState =
(color == null ? AllBlocks.SAIL_FRAME : AllBlocks.DYED_SAILS[color.ordinal()]).getDefaultState()
.with(FACING, state.get(FACING));
// Dye the block itself
if (state != newState) {
@ -142,7 +152,7 @@ public class SailBlock extends ProperDirectionalBlock {
continue;
BlockState adjacentState = world.getBlockState(offset);
Block block = adjacentState.getBlock();
if (!(block instanceof SailBlock) || ((SailBlock) block).frame)
if (!(block instanceof SailBlock) || ((SailBlock) block).frame && color != null)
continue;
if (state != adjacentState)
world.setBlockState(offset, newState);
@ -165,13 +175,14 @@ public class SailBlock extends ProperDirectionalBlock {
return AllShapes.SAIL_FRAME_COLLISION.get(state.get(FACING));
return getShape(state, p_220071_2_, p_220071_3_, p_220071_4_);
}
@Override
public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos,
PlayerEntity player) {
ItemStack pickBlock = super.getPickBlock(state, target, world, pos, player);
if (pickBlock.isEmpty())
return AllBlocks.SAIL.get().getPickBlock(state, target, world, pos, player);
return AllBlocks.SAIL.get()
.getPickBlock(state, target, world, pos, player);
return pickBlock;
}

View file

@ -0,0 +1,109 @@
package com.simibubi.create.content.contraptions.components.structureMovement.pulley;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
public abstract class AbstractPulleyRenderer extends KineticTileEntityRenderer {
private AllBlockPartials halfRope;
private AllBlockPartials halfMagnet;
public AbstractPulleyRenderer(TileEntityRendererDispatcher dispatcher, AllBlockPartials halfRope,
AllBlockPartials halfMagnet) {
super(dispatcher);
this.halfRope = halfRope;
this.halfMagnet = halfMagnet;
}
@Override
public boolean isGlobalRenderer(KineticTileEntity p_188185_1_) {
return true;
}
@Override
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
int light, int overlay) {
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
float offset = getOffset(te, partialTicks);
boolean running = isRunning(te);
Axis rotationAxis = ((IRotate) te.getBlockState()
.getBlock()).getRotationAxis(te.getBlockState());
kineticRotationTransform(getRotatedCoil(te), te, rotationAxis, AngleHelper.rad(offset * 180), light)
.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
World world = te.getWorld();
BlockState blockState = te.getBlockState();
BlockPos pos = te.getPos();
SuperByteBuffer halfMagnet = this.halfMagnet.renderOn(blockState);
SuperByteBuffer halfRope = this.halfRope.renderOn(blockState);
SuperByteBuffer magnet = renderMagnet(te);
SuperByteBuffer rope = renderRope(te);
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
if (running || offset == 0)
renderAt(world, offset > .25f ? magnet : halfMagnet, offset, pos, ms, vb);
float f = offset % 1;
if (offset > .75f && (f < .25f || f > .75f))
renderAt(world, halfRope, f > .75f ? f - 1 : f, pos, ms, vb);
if (!running)
return;
for (int i = 0; i < offset - 1.25f; i++)
renderAt(world, rope, offset - i - 1, pos, ms, vb);
}
private void renderAt(IWorld world, SuperByteBuffer partial, float offset, BlockPos pulleyPos, MatrixStack ms,
IVertexBuilder buffer) {
BlockPos actualPos = pulleyPos.down((int) offset);
int light = WorldRenderer.getLightmapCoordinates(world, world.getBlockState(actualPos), actualPos);
partial.translate(0, -offset, 0)
.light(light)
.renderInto(ms, buffer);
}
protected abstract Axis getShaftAxis(KineticTileEntity te);
protected abstract AllBlockPartials getCoil();
protected abstract SuperByteBuffer renderRope(KineticTileEntity te);
protected abstract SuperByteBuffer renderMagnet(KineticTileEntity te);
protected abstract float getOffset(KineticTileEntity te, float partialTicks);
protected abstract boolean isRunning(KineticTileEntity te);
@Override
protected BlockState getRenderedBlockState(KineticTileEntity te) {
return shaft(getShaftAxis(te));
}
protected SuperByteBuffer getRotatedCoil(KineticTileEntity te) {
BlockState blockState = te.getBlockState();
return getCoil().renderOnDirectionalSouth(blockState,
Direction.getFacingFromAxis(AxisDirection.POSITIVE, getShaftAxis(te)));
}
}

View file

@ -1,53 +1,45 @@
package com.simibubi.create.content.contraptions.components.structureMovement.pulley;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
public class PulleyRenderer extends KineticTileEntityRenderer {
public class PulleyRenderer extends AbstractPulleyRenderer {
public PulleyRenderer(TileEntityRendererDispatcher dispatcher) {
super(dispatcher);
}
@Override
public boolean isGlobalRenderer(KineticTileEntity p_188185_1_) {
return true;
super(dispatcher, AllBlockPartials.ROPE_HALF, AllBlockPartials.ROPE_HALF_MAGNET);
}
@Override
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
int light, int overlay) {
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
protected Axis getShaftAxis(KineticTileEntity te) {
return te.getBlockState().get(PulleyBlock.HORIZONTAL_AXIS);
}
@Override
protected AllBlockPartials getCoil() {
return AllBlockPartials.ROPE_COIL;
}
@Override
protected SuperByteBuffer renderRope(KineticTileEntity te) {
return CreateClient.bufferCache.renderBlock(AllBlocks.ROPE.getDefaultState());
}
@Override
protected SuperByteBuffer renderMagnet(KineticTileEntity te) {
return CreateClient.bufferCache.renderBlock(AllBlocks.PULLEY_MAGNET.getDefaultState());
}
@Override
protected float getOffset(KineticTileEntity te, float partialTicks) {
PulleyTileEntity pulley = (PulleyTileEntity) te;
World world = te.getWorld();
BlockState blockState = te.getBlockState();
BlockPos pos = te.getPos();
SuperByteBuffer halfMagnet = AllBlockPartials.ROPE_HALF_MAGNET.renderOn(blockState);
SuperByteBuffer halfRope = AllBlockPartials.ROPE_HALF.renderOn(blockState);
SuperByteBuffer magnet = CreateClient.bufferCache.renderBlock(AllBlocks.PULLEY_MAGNET.getDefaultState());
SuperByteBuffer rope = CreateClient.bufferCache.renderBlock(AllBlocks.ROPE.getDefaultState());
boolean running = pulley.running;
boolean moving = running && (pulley.movedContraption == null || !pulley.movedContraption.isStalled());
float offset = pulley.getInterpolatedOffset(moving ? partialTicks : 0.5f);
@ -56,45 +48,16 @@ public class PulleyRenderer extends KineticTileEntityRenderer {
ContraptionEntity e = pulley.movedContraption;
PulleyContraption c = (PulleyContraption) pulley.movedContraption.getContraption();
double entityPos = MathHelper.lerp(partialTicks, e.lastTickPosY, e.getY());
offset = (float) -(entityPos - c.getAnchor().getY() - c.initialOffset);
offset = (float) -(entityPos - c.getAnchor()
.getY() - c.initialOffset);
}
renderPulleyRope(ms, buffer, world, pos, halfMagnet, halfRope, magnet, rope, running, offset);
}
public static void renderPulleyRope(MatrixStack ms, IRenderTypeBuffer buffer, World world, BlockPos pos,
SuperByteBuffer halfMagnet, SuperByteBuffer halfRope, SuperByteBuffer magnet, SuperByteBuffer rope,
boolean running, float offset) {
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
if (running || offset == 0)
renderAt(world, offset > .25f ? magnet : halfMagnet, offset, pos, ms, vb);
float f = offset % 1;
if (offset > .75f && (f < .25f || f > .75f))
renderAt(world, halfRope, f > .75f ? f - 1 : f, pos, ms, vb);
if (!running)
return;
for (int i = 0; i < offset - 1.25f; i++)
renderAt(world, rope, offset - i - 1, pos, ms, vb);
}
public static void renderAt(IWorld world, SuperByteBuffer partial, float offset, BlockPos pulleyPos,
MatrixStack ms, IVertexBuilder buffer) {
BlockPos actualPos = pulleyPos.down((int) offset);
int light = WorldRenderer.getLightmapCoordinates(world, world.getBlockState(actualPos), actualPos);
partial.translate(0, -offset, 0).light(light).renderInto(ms, buffer);
return offset;
}
@Override
protected SuperByteBuffer getRotatedModel(KineticTileEntity te) {
BlockState blockState = te.getBlockState();
return AllBlockPartials.ROPE_COIL.renderOnDirectionalSouth(blockState, horizontalFacing(blockState));
}
public Direction horizontalFacing(BlockState blockState) {
return Direction.getFacingFromAxis(AxisDirection.POSITIVE, blockState.get(PulleyBlock.HORIZONTAL_AXIS));
protected boolean isRunning(KineticTileEntity te) {
return ((PulleyTileEntity) te).running;
}
}

View file

@ -52,7 +52,6 @@ public class OpenEndedPipe {
.isReplaceable())
return;
// TODO different pipe end types
if (pulling) {
if (fluidState.isEmpty() || !fluidState.isSource())
return;

View file

@ -1,70 +1,50 @@
package com.simibubi.create.content.contraptions.fluids.actors;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyRenderer;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.AbstractPulleyRenderer;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class HosePulleyRenderer extends KineticTileEntityRenderer {
public class HosePulleyRenderer extends AbstractPulleyRenderer {
public HosePulleyRenderer(TileEntityRendererDispatcher dispatcher) {
super(dispatcher);
super(dispatcher, AllBlockPartials.HOSE_HALF, AllBlockPartials.HOSE_HALF_MAGNET);
}
@Override
public boolean isGlobalRenderer(KineticTileEntity p_188185_1_) {
protected Axis getShaftAxis(KineticTileEntity te) {
return te.getBlockState()
.get(HosePulleyBlock.HORIZONTAL_FACING)
.rotateY()
.getAxis();
}
@Override
protected AllBlockPartials getCoil() {
return AllBlockPartials.HOSE_COIL;
}
@Override
protected SuperByteBuffer renderRope(KineticTileEntity te) {
return AllBlockPartials.HOSE.renderOn(te.getBlockState());
}
@Override
protected SuperByteBuffer renderMagnet(KineticTileEntity te) {
return AllBlockPartials.HOSE_MAGNET.renderOn(te.getBlockState());
}
@Override
protected float getOffset(KineticTileEntity te, float partialTicks) {
return ((HosePulleyTileEntity) te).getInterpolatedOffset(partialTicks);
}
@Override
protected boolean isRunning(KineticTileEntity te) {
return true;
}
@Override
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
int light, int overlay) {
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
HosePulleyTileEntity pulley = (HosePulleyTileEntity) te;
float offset = pulley.getInterpolatedOffset(partialTicks);
Axis rotationAxis = ((IRotate) te.getBlockState()
.getBlock()).getRotationAxis(te.getBlockState());
kineticRotationTransform(getRotatedCoil(te), te, rotationAxis, AngleHelper.rad(offset * 180), light).renderInto(ms,
buffer.getBuffer(RenderType.getSolid()));
World world = te.getWorld();
BlockState blockState = te.getBlockState();
BlockPos pos = te.getPos();
SuperByteBuffer halfMagnet = AllBlockPartials.HOSE_HALF_MAGNET.renderOn(blockState);
SuperByteBuffer halfRope = AllBlockPartials.HOSE_HALF.renderOn(blockState);
SuperByteBuffer magnet = AllBlockPartials.HOSE_MAGNET.renderOn(blockState);
SuperByteBuffer rope = AllBlockPartials.HOSE.renderOn(blockState);
PulleyRenderer.renderPulleyRope(ms, buffer, world, pos, halfMagnet, halfRope, magnet, rope, true, offset);
}
@Override
protected BlockState getRenderedBlockState(KineticTileEntity te) {
return shaft(te.getBlockState()
.get(HosePulleyBlock.HORIZONTAL_FACING)
.rotateY()
.getAxis());
}
protected SuperByteBuffer getRotatedCoil(KineticTileEntity te) {
BlockState blockState = te.getBlockState();
return AllBlockPartials.HOSE_COIL.renderOnDirectionalSouth(blockState,
blockState.get(HosePulleyBlock.HORIZONTAL_FACING)
.rotateY());
}
}

View file

@ -1,24 +1,71 @@
package com.simibubi.create.content.contraptions.fluids.actors;
import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.fluid.FluidHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemGroup;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.InventoryHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.NonNullList;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
public class ItemDrainBlock extends Block {
public class ItemDrainBlock extends Block implements IWrenchable, ITE<ItemDrainTileEntity> {
public ItemDrainBlock(Properties p_i48440_1_) {
super(p_i48440_1_);
}
@Override
public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
ItemStack heldItem = player.getHeldItem(handIn);
try {
ItemDrainTileEntity te = getTileEntity(worldIn, pos);
if (!heldItem.isEmpty()) {
te.internalTank.allowInsertion();
ActionResultType tryExchange = tryExchange(worldIn, player, handIn, heldItem, te);
te.internalTank.forbidInsertion();
if (tryExchange.isAccepted())
return tryExchange;
}
ItemStack heldItemStack = te.getHeldItemStack();
if (!worldIn.isRemote && !heldItemStack.isEmpty()) {
player.inventory.placeItemBackInInventory(worldIn, heldItemStack);
te.heldItem = null;
te.notifyUpdate();
}
return ActionResultType.SUCCESS;
} catch (TileEntityException e) {
}
return ActionResultType.PASS;
}
protected ActionResultType tryExchange(World worldIn, PlayerEntity player, Hand handIn, ItemStack heldItem,
ItemDrainTileEntity te) {
if (FluidHelper.tryEmptyItemIntoTE(worldIn, player, handIn, heldItem, te))
return ActionResultType.SUCCESS;
if (EmptyingByBasin.canItemBeEmptied(worldIn, heldItem))
return ActionResultType.SUCCESS;
return ActionResultType.PASS;
}
@Override
public VoxelShape getShape(BlockState p_220053_1_, IBlockReader p_220053_2_, BlockPos p_220053_3_,
ISelectionContext p_220053_4_) {
@ -26,6 +73,30 @@ public class ItemDrainBlock extends Block {
}
@Override
public void fillItemGroup(ItemGroup p_149666_1_, NonNullList<ItemStack> p_149666_2_) {}
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (!state.hasTileEntity() || state.getBlock() == newState.getBlock())
return;
withTileEntityDo(worldIn, pos, te -> {
ItemStack heldItemStack = te.getHeldItemStack();
if (!heldItemStack.isEmpty())
InventoryHelper.spawnItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(), heldItemStack);
});
worldIn.removeTileEntity(pos);
}
@Override
public boolean hasTileEntity(BlockState state) {
return true;
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return AllTileEntities.ITEM_DRAIN.create();
}
@Override
public Class<ItemDrainTileEntity> getTileEntityClass() {
return ItemDrainTileEntity.class;
}
}

View file

@ -0,0 +1,70 @@
package com.simibubi.create.content.contraptions.fluids.actors;
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraftforge.items.IItemHandler;
public class ItemDrainItemHandler implements IItemHandler {
private ItemDrainTileEntity te;
private Direction side;
public ItemDrainItemHandler(ItemDrainTileEntity te, Direction side) {
this.te = te;
this.side = side;
}
@Override
public int getSlots() {
return 1;
}
@Override
public ItemStack getStackInSlot(int slot) {
return te.getHeldItemStack();
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (!te.getHeldItemStack()
.isEmpty())
return stack;
if (!simulate) {
TransportedItemStack heldItem = new TransportedItemStack(stack);
heldItem.prevBeltPosition = 0;
te.setHeldItem(heldItem, side.getOpposite());
te.notifyUpdate();
}
return ItemStack.EMPTY;
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
TransportedItemStack held = te.heldItem;
if (held == null)
return ItemStack.EMPTY;
ItemStack stack = held.stack.copy();
ItemStack extracted = stack.split(amount);
if (!simulate) {
te.heldItem.stack = stack;
if (stack.isEmpty())
te.heldItem = null;
te.notifyUpdate();
}
return extracted;
}
@Override
public int getSlotLimit(int slot) {
return 64;
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
return true;
}
}

View file

@ -0,0 +1,182 @@
package com.simibubi.create.content.contraptions.fluids.actors;
import java.util.Random;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
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.MatrixStacker;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fluids.FluidStack;
public class ItemDrainRenderer extends SmartTileEntityRenderer<ItemDrainTileEntity> {
public ItemDrainRenderer(TileEntityRendererDispatcher dispatcher) {
super(dispatcher);
}
@Override
protected void renderSafe(ItemDrainTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
int light, int overlay) {
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
renderFluid(te, partialTicks, ms, buffer, light);
renderItem(te, partialTicks, ms, buffer, light, overlay);
}
protected void renderItem(ItemDrainTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
int light, int overlay) {
TransportedItemStack transported = te.heldItem;
if (transported == null)
return;
MatrixStacker msr = MatrixStacker.of(ms);
Vec3d itemPosition = VecHelper.getCenterOf(te.getPos());
Direction insertedFrom = transported.insertedFrom;
if (!insertedFrom.getAxis()
.isHorizontal())
return;
ms.push();
ms.translate(.5f, 15 / 16f, .5f);
msr.nudge(0);
float offset = MathHelper.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition);
float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset);
Vec3d offsetVec = new Vec3d(insertedFrom.getOpposite()
.getDirectionVec()).scale(.5f - offset);
ms.translate(offsetVec.x, offsetVec.y, offsetVec.z);
boolean alongX = insertedFrom.rotateY()
.getAxis() == Axis.X;
if (!alongX)
sideOffset *= -1;
ms.translate(alongX ? sideOffset : 0, 0, alongX ? 0 : sideOffset);
ItemStack itemStack = transported.stack;
Random r = new Random(0);
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
int count = (int) (MathHelper.log2((int) (itemStack.getCount()))) / 2;
boolean renderUpright = BeltHelper.isItemUpright(itemStack);
boolean blockItem = itemRenderer.getItemModelWithOverrides(itemStack, null, null)
.isGui3d();
if (renderUpright)
ms.translate(0, 3 / 32d, 0);
int positive = insertedFrom.getAxisDirection()
.getOffset();
float verticalAngle = positive * offset * 360;
if (insertedFrom.getAxis() != Axis.X)
msr.rotateX(verticalAngle);
if (insertedFrom.getAxis() != Axis.Z)
msr.rotateZ(-verticalAngle);
if (renderUpright) {
Entity renderViewEntity = Minecraft.getInstance().renderViewEntity;
if (renderViewEntity != null) {
Vec3d positionVec = renderViewEntity.getPositionVec();
Vec3d vectorForOffset = itemPosition.add(offsetVec);
Vec3d diff = vectorForOffset.subtract(positionVec);
if (insertedFrom.getAxis() != Axis.X)
diff = VecHelper.rotate(diff, verticalAngle, Axis.X);
if (insertedFrom.getAxis() != Axis.Z)
diff = VecHelper.rotate(diff, -verticalAngle, Axis.Z);
float yRot = (float) MathHelper.atan2(diff.z, -diff.x);
ms.multiply(Vector3f.POSITIVE_Y.getRadialQuaternion((float) (yRot - Math.PI / 2)));
}
ms.translate(0, 0, -1/16f);
}
for (int i = 0; i <= count; i++) {
ms.push();
if (blockItem)
ms.translate(r.nextFloat() * .0625f * i, 0, r.nextFloat() * .0625f * i);
ms.scale(.5f, .5f, .5f);
if (!blockItem && !renderUpright)
msr.rotateX(90);
itemRenderer.renderItem(itemStack, TransformType.FIXED, light, overlay, ms, buffer);
ms.pop();
if (!renderUpright) {
if (!blockItem)
msr.rotateY(10);
ms.translate(0, blockItem ? 1 / 64d : 1 / 16d, 0);
} else
ms.translate(0, 0, -1 / 16f);
}
ms.pop();
}
protected void renderFluid(ItemDrainTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
int light) {
SmartFluidTankBehaviour tank = te.internalTank;
if (tank == null)
return;
TankSegment primaryTank = tank.getPrimaryTank();
FluidStack fluidStack = primaryTank.getRenderedFluid();
float level = primaryTank.getFluidLevel()
.getValue(partialTicks);
if (!fluidStack.isEmpty() && level != 0) {
float yMin = 4f / 16f;
float min = 2f / 16f;
float max = min + (12 / 16f);
float yOffset = (8 / 16f) * level;
ms.push();
ms.translate(0, yOffset, 0);
FluidRenderer.renderTiledFluidBB(fluidStack, min, yMin - yOffset, min, max, yMin, max, buffer, ms, light,
false);
ms.pop();
}
ItemStack heldItemStack = te.getHeldItemStack();
if (heldItemStack.isEmpty())
return;
FluidStack fluidStack2 = EmptyingByBasin.emptyItem(te.getWorld(), heldItemStack, true)
.getFirst();
if (fluidStack2.isEmpty()) {
if (fluidStack.isEmpty())
return;
fluidStack2 = fluidStack;
}
int processingTicks = te.processingTicks;
float processingPT = te.processingTicks - partialTicks;
float processingProgress = 1 - (processingPT - 5) / 10;
processingProgress = MathHelper.clamp(processingProgress, 0, 1);
float radius = 0;
if (processingTicks != -1) {
radius = (float) (Math.pow(((2 * processingProgress) - 1), 2) - 1);
AxisAlignedBB bb = new AxisAlignedBB(0.5, 1.0, 0.5, 0.5, 0.25, 0.5).grow(radius / 32f);
FluidRenderer.renderTiledFluidBB(fluidStack2, (float) bb.minX, (float) bb.minY, (float) bb.minZ,
(float) bb.maxX, (float) bb.maxY, (float) bb.maxZ, buffer, ms, light, true);
}
}
}

View file

@ -0,0 +1,257 @@
package com.simibubi.create.content.contraptions.fluids.actors;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.Block;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
public class ItemDrainTileEntity extends SmartTileEntity {
public static final int FILLING_TIME = 20;
SmartFluidTankBehaviour internalTank;
TransportedItemStack heldItem;
protected int processingTicks;
Map<Direction, LazyOptional<ItemDrainItemHandler>> itemHandlers;
public ItemDrainTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
itemHandlers = new IdentityHashMap<>();
for (Direction d : Iterate.horizontalDirections) {
ItemDrainItemHandler itemDrainItemHandler = new ItemDrainItemHandler(this, d);
itemHandlers.put(d, LazyOptional.of(() -> itemDrainItemHandler));
}
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
behaviours.add(new DirectBeltInputBehaviour(this).setInsertionHandler(this::tryInsertingFromSide));
behaviours.add(internalTank = SmartFluidTankBehaviour.single(this, 1500)
.allowExtraction()
.forbidInsertion());
}
private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) {
ItemStack inserted = transportedStack.stack;
ItemStack empty = ItemStack.EMPTY;
if (!getHeldItemStack().isEmpty())
return inserted;
if (simulate)
return empty;
transportedStack = transportedStack.copy();
transportedStack.beltPosition = side.getAxis()
.isVertical() ? .5f : 0;
transportedStack.prevSideOffset = transportedStack.sideOffset;
transportedStack.prevBeltPosition = transportedStack.beltPosition;
setHeldItem(transportedStack, side);
markDirty();
sendData();
return empty;
}
public ItemStack getHeldItemStack() {
return heldItem == null ? ItemStack.EMPTY : heldItem.stack;
}
@Override
public void tick() {
super.tick();
if (heldItem == null) {
processingTicks = 0;
return;
}
if (processingTicks > 0) {
heldItem.prevBeltPosition = .5f;
boolean wasAtBeginning = processingTicks == FILLING_TIME;
if (!world.isRemote || processingTicks < FILLING_TIME)
processingTicks--;
if (!continueProcessing()) {
processingTicks = 0;
notifyUpdate();
return;
}
if (wasAtBeginning != (processingTicks == FILLING_TIME))
sendData();
return;
}
heldItem.prevBeltPosition = heldItem.beltPosition;
heldItem.prevSideOffset = heldItem.sideOffset;
heldItem.beltPosition += itemMovementPerTick();
if (heldItem.beltPosition > 1) {
heldItem.beltPosition = 1;
if (world.isRemote)
return;
Direction side = heldItem.insertedFrom;
BlockPos nextPosition = pos.offset(side);
DirectBeltInputBehaviour directBeltInputBehaviour =
TileEntityBehaviour.get(world, nextPosition, DirectBeltInputBehaviour.TYPE);
if (directBeltInputBehaviour == null) {
if (!Block.hasSolidSide(world.getBlockState(nextPosition), world, nextPosition, side.getOpposite())) {
ItemStack ejected = heldItem.stack;
Vec3d outPos = VecHelper.getCenterOf(pos)
.add(new Vec3d(side.getDirectionVec()).scale(.75));
float movementSpeed = itemMovementPerTick();
Vec3d outMotion = new Vec3d(side.getDirectionVec()).scale(movementSpeed)
.add(0, 1 / 8f, 0);
outPos.add(outMotion.normalize());
ItemEntity entity = new ItemEntity(world, outPos.x, outPos.y + 6 / 16f, outPos.z, ejected);
entity.setMotion(outMotion);
entity.setDefaultPickupDelay();
entity.velocityChanged = true;
world.addEntity(entity);
heldItem = null;
notifyUpdate();
}
return;
}
if (!directBeltInputBehaviour.canInsertFromSide(side))
return;
ItemStack returned = directBeltInputBehaviour.handleInsertion(heldItem.copy(), side, false);
if (returned.isEmpty()) {
heldItem = null;
notifyUpdate();
return;
}
if (returned.getCount() != heldItem.stack.getCount()) {
heldItem.stack = returned;
notifyUpdate();
return;
}
return;
}
if (heldItem.prevBeltPosition < .5f && heldItem.beltPosition >= .5f) {
if (!EmptyingByBasin.canItemBeEmptied(world, heldItem.stack))
return;
heldItem.beltPosition = .5f;
if (world.isRemote)
return;
processingTicks = FILLING_TIME;
sendData();
}
}
protected boolean continueProcessing() {
if (world.isRemote)
return true;
if (processingTicks < 5)
return true;
if (!EmptyingByBasin.canItemBeEmptied(world, heldItem.stack))
return false;
Pair<FluidStack, ItemStack> emptyItem = EmptyingByBasin.emptyItem(world, heldItem.stack, true);
FluidStack fluidFromItem = emptyItem.getFirst();
if (processingTicks > 5) {
internalTank.allowInsertion();
if (internalTank.getPrimaryHandler()
.fill(fluidFromItem, FluidAction.SIMULATE) != fluidFromItem.getAmount()) {
internalTank.forbidInsertion();
processingTicks = FILLING_TIME;
return true;
}
internalTank.forbidInsertion();
return true;
}
emptyItem = EmptyingByBasin.emptyItem(world, heldItem.stack.copy(), false);
// Process finished
ItemStack out = emptyItem.getSecond();
if (!out.isEmpty())
heldItem.stack = out;
else
heldItem = null;
internalTank.allowInsertion();
internalTank.getPrimaryHandler()
.fill(fluidFromItem, FluidAction.EXECUTE);
internalTank.forbidInsertion();
notifyUpdate();
return true;
}
private float itemMovementPerTick() {
return 1 / 8f;
}
@Override
public void remove() {
super.remove();
for (LazyOptional<ItemDrainItemHandler> lazyOptional : itemHandlers.values())
lazyOptional.invalidate();
}
public void setHeldItem(TransportedItemStack heldItem, Direction insertedFrom) {
this.heldItem = heldItem;
this.heldItem.insertedFrom = insertedFrom;
}
@Override
public void write(CompoundNBT compound, boolean clientPacket) {
compound.putInt("ProcessingTicks", processingTicks);
if (heldItem != null)
compound.put("HeldItem", heldItem.serializeNBT());
super.write(compound, clientPacket);
}
@Override
protected void read(CompoundNBT compound, boolean clientPacket) {
heldItem = null;
processingTicks = compound.getInt("ProcessingTicks");
if (compound.contains("HeldItem"))
heldItem = TransportedItemStack.read(compound.getCompound("HeldItem"));
super.read(compound, clientPacket);
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (side != null && side.getAxis()
.isHorizontal() && isItemHandlerCap(cap))
return itemHandlers.get(side)
.cast();
if (side != Direction.UP && isFluidHandlerCap(cap))
return internalTank.getCapability()
.cast();
return super.getCapability(cap, side);
}
}

View file

@ -38,7 +38,8 @@ import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fml.ModList;
public class SpoutTileEntity extends SmartTileEntity {
private static final boolean IS_TIC_LOADED = ModList.get().isLoaded("tconstruct");
private static final boolean IS_TIC_LOADED = ModList.get()
.isLoaded("tconstruct");
private static final Class<?> CASTING_FLUID_HANDLER_CLASS;
static {
Class<?> testClass;
@ -51,12 +52,12 @@ public class SpoutTileEntity extends SmartTileEntity {
}
public static final int FILLING_TIME = 20;
protected BeltProcessingBehaviour beltProcessing;
protected int processingTicks;
protected boolean sendSplash;
private boolean shouldAnimate = true;
SmartFluidTankBehaviour tank;
public SpoutTileEntity(TileEntityType<?> tileEntityTypeIn) {
@ -73,11 +74,11 @@ public class SpoutTileEntity extends SmartTileEntity {
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
tank = SmartFluidTankBehaviour.single(this, 1000);
behaviours.add(tank);
beltProcessing = new BeltProcessingBehaviour(this).whenItemEnters(this::onItemReceived)
.whileItemHeld(this::whenItemHeld);
behaviours.add(beltProcessing);
}
protected ProcessingResult onItemReceived(TransportedItemStack transported,
@ -126,7 +127,8 @@ public class SpoutTileEntity extends SmartTileEntity {
handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(outList, held));
}
tank.getPrimaryHandler().setFluid(fluid);
tank.getPrimaryHandler()
.setFluid(fluid);
sendSplash = true;
notifyUpdate();
return PASS;
@ -137,7 +139,8 @@ public class SpoutTileEntity extends SmartTileEntity {
return;
if (world == null)
return;
IFluidHandler localTank = this.tank.getCapability().orElse(null);
IFluidHandler localTank = this.tank.getCapability()
.orElse(null);
if (localTank == null)
return;
FluidStack fluid = getCurrentFluidInTank();
@ -177,20 +180,22 @@ public class SpoutTileEntity extends SmartTileEntity {
handler.fill(fillStack, IFluidHandler.FluidAction.EXECUTE);
}
}
tank.getPrimaryHandler().setFluid(fluid);
tank.getPrimaryHandler()
.setFluid(fluid);
this.notifyUpdate();
}
}
}
private FluidStack getCurrentFluidInTank() {
return tank.getPrimaryHandler().getFluid();
return tank.getPrimaryHandler()
.getFluid();
}
@Override
protected void write(CompoundNBT compound, boolean clientPacket) {
super.write(compound, clientPacket);
compound.putInt("ProcessingTicks", processingTicks);
if (sendSplash && clientPacket) {
compound.putBoolean("Splash", true);
@ -205,24 +210,26 @@ public class SpoutTileEntity extends SmartTileEntity {
if (!clientPacket)
return;
if (compound.contains("Splash"))
spawnSplash(tank.getPrimaryTank().getRenderedFluid());
spawnSplash(tank.getPrimaryTank()
.getRenderedFluid());
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY && side != Direction.DOWN)
return tank.getCapability().cast();
return tank.getCapability()
.cast();
return super.getCapability(cap, side);
}
public void tick() {
super.tick();
processTicCastBlock();
if (processingTicks >= 0)
processingTicks--;
if (processingTicks >= 8 && world.isRemote && shouldAnimate)
spawnProcessingParticles(tank.getPrimaryTank().getRenderedFluid());
spawnProcessingParticles(tank.getPrimaryTank()
.getRenderedFluid());
}
protected void spawnProcessingParticles(FluidStack fluid) {
@ -255,12 +262,13 @@ public class SpoutTileEntity extends SmartTileEntity {
return null;
} else {
TileEntity te = this.world.getTileEntity(pos);
return te != null ? te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction).orElse(null) : null;
return te != null ? te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction)
.orElse(null) : null;
}
}
public int getCorrectedProcessingTicks() {
if(shouldAnimate)
if (shouldAnimate)
return processingTicks;
return -1;
}

View file

@ -6,6 +6,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Random;
import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.foundation.block.connected.CTModel;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.utility.Iterate;
@ -23,7 +24,15 @@ public class FluidTankModel extends CTModel {
protected static ModelProperty<CullData> CULL_PROPERTY = new ModelProperty<>();
public FluidTankModel(IBakedModel originalModel, CTSpriteShiftEntry side, CTSpriteShiftEntry top) {
public static FluidTankModel standard(IBakedModel originalModel) {
return new FluidTankModel(originalModel, AllSpriteShifts.FLUID_TANK, AllSpriteShifts.COPPER_CASING);
}
public static FluidTankModel creative(IBakedModel originalModel) {
return new FluidTankModel(originalModel, AllSpriteShifts.CREATIVE_FLUID_TANK, AllSpriteShifts.CREATIVE_CASING);
}
private FluidTankModel(IBakedModel originalModel, CTSpriteShiftEntry side, CTSpriteShiftEntry top) {
super(originalModel, new FluidTankCTBehaviour(side, top));
}

View file

@ -101,10 +101,8 @@ public class DepotBlock extends Block implements ITE<DepotTileEntity> {
@Override
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (!state.hasTileEntity() || state.getBlock() == newState.getBlock()) {
if (!state.hasTileEntity() || state.getBlock() == newState.getBlock())
return;
}
withTileEntityDo(worldIn, pos, te -> {
ItemHelper.dropContents(worldIn, pos, te.processingOutputBuffer);
if (!te.getHeldItemStack()

View file

@ -48,7 +48,8 @@ public class DepotRenderer extends SafeTileEntityRenderer<DepotTileEntity> {
if (transported.insertedFrom.getAxis()
.isHorizontal()) {
Vector3d offsetVec = Vector3d.of(transported.insertedFrom.getOpposite()
.getDirectionVec()).scale(.5f - offset);
.getDirectionVec())
.scale(.5f - offset);
ms.translate(offsetVec.x, offsetVec.y, offsetVec.z);
boolean alongX = transported.insertedFrom.rotateY()
.getAxis() == Axis.X;
@ -86,7 +87,7 @@ public class DepotRenderer extends SafeTileEntityRenderer<DepotTileEntity> {
ms.pop();
}
protected void renderItem(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, ItemStack itemStack,
public static void renderItem(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, ItemStack itemStack,
int angle, Random r, Vector3d itemPosition) {
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();

View file

@ -6,6 +6,8 @@ import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock;
import com.simibubi.create.content.logistics.block.depot.DepotBlock;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.VoxelShaper;
import com.tterrag.registrate.util.entry.BlockEntry;
@ -107,7 +109,7 @@ public abstract class BeltFunnelBlock extends HorizontalInteractionFunnelBlock {
public static BlockState updateShape(BlockState state, IBlockReader world, BlockPos pos) {
state = state.with(SHAPE, Shape.RETRACTED);
Direction horizontalFacing = state.get(HORIZONTAL_FACING);
BlockState below = world.getBlockState(pos.down());
if (below.getBlock() instanceof BeltBlock && below.get(BeltBlock.HORIZONTAL_FACING)
.getAxis() != horizontalFacing.getAxis())
@ -129,6 +131,17 @@ public abstract class BeltFunnelBlock extends HorizontalInteractionFunnelBlock {
return false;
}
@Override
public void onReplaced(BlockState p_196243_1_, World p_196243_2_, BlockPos p_196243_3_, BlockState p_196243_4_,
boolean p_196243_5_) {
if (p_196243_1_.hasTileEntity()
&& (p_196243_1_.getBlock() != p_196243_4_.getBlock() && !FunnelBlock.isFunnel(p_196243_4_)
|| !p_196243_4_.hasTileEntity())) {
TileEntityBehaviour.destroy(p_196243_2_, p_196243_3_, FilteringBehaviour.TYPE);
p_196243_2_.removeTileEntity(p_196243_3_);
}
}
@Override
protected boolean canStillInteract(BlockState state, IWorldReader world, BlockPos pos) {
return isOnValidBelt(state, world, pos);

View file

@ -32,7 +32,7 @@ public class FunnelFilterSlotPositioning extends ValueBoxTransform.Sided {
if (!funnelFacing.getAxis()
.isHorizontal()) {
Vector3d southLocation = VecHelper.voxelSpace(8, 13, 15.5f);
Vector3d southLocation = VecHelper.voxelSpace(8, funnelFacing == Direction.DOWN ? 3 : 13, 15.5f);
return VecHelper.rotateCentered(southLocation, horizontalAngle, Axis.Y);
}
@ -48,7 +48,7 @@ public class FunnelFilterSlotPositioning extends ValueBoxTransform.Sided {
float zRotLast = alongX ^ funnelFacing.getAxisDirection() == AxisDirection.POSITIVE ? 180 : 0;
if (reverse)
zRotLast += 180;
Vector3d vec = VecHelper.voxelSpace(8, 13, .5f);
vec = vec.subtract(.5, .5, .5);
vec = VecHelper.rotate(vec, zRotLast, Axis.Z);

View file

@ -79,6 +79,8 @@ public class StockpileSwitchBlock extends HorizontalBlock implements ITE<Stockpi
@Override
public int getWeakPower(BlockState blockState, IBlockReader blockAccess, BlockPos pos, Direction side) {
if (side == blockState.get(HORIZONTAL_FACING).getOpposite())
return 0;
try {
return getTileEntity(blockAccess, pos).isPowered() ? 15 : 0;
} catch (TileEntityException e) {

View file

@ -370,13 +370,12 @@ public class StandardRecipeGen extends CreateRecipeProvider {
ENCASED_FAN = create(AllBlocks.ENCASED_FAN).unlockedByTag(I::ironSheet)
.viaShaped(b -> b.key('S', I.shaft())
.key('A', I.andesite())
.key('R', ItemTags.PLANKS)
.key('B', Items.IRON_BARS)
.key('A', I.andesiteCasing())
.key('R', I.cog())
.key('P', AllItems.PROPELLER.get())
.patternLine(" S ")
.patternLine("RAR")
.patternLine("BPB")),
.patternLine(" P ")),
CUCKOO_CLOCK = create(AllBlocks.CUCKOO_CLOCK).unlockedBy(I::andesite)
.viaShaped(b -> b.key('S', ItemTags.PLANKS)
@ -458,6 +457,13 @@ public class StandardRecipeGen extends CreateRecipeProvider {
.patternLine("T")
.patternLine("P")
.patternLine("S")),
ITEM_DRAIN = create(AllBlocks.ITEM_DRAIN).unlockedBy(I::copperCasing)
.viaShaped(b -> b
.key('P', Blocks.IRON_BARS)
.key('S', I.copperCasing())
.patternLine("P")
.patternLine("S")),
FLUID_TANK = create(AllBlocks.FLUID_TANK).returns(2)
.unlockedBy(I::copperCasing)

View file

@ -226,7 +226,7 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour {
protected FluidStack renderedFluid;
public TankSegment(int capacity) {
tank = new SmartFluidTank(1000, f -> onFluidStackChanged());
tank = new SmartFluidTank(capacity, f -> onFluidStackChanged());
fluidLevel = LerpedFloat.linear()
.startWithValue(0)
.chase(0, .25, Chaser.EXP);

View file

@ -2,8 +2,6 @@
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"0": "create:block/axis",
"1": "create:block/axis_top",
"5": "create:block/pulley_rope"
},
"elements": [
@ -37,7 +35,7 @@
"name": "coil",
"from": [3.5, 3.5, 3],
"to": [12.5, 12.5, 7],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, -10]},
"rotation": {"angle": -45, "axis": "z", "origin": [8, 8, -10]},
"faces": {
"north": {"uv": [0, 0, 9, 9], "texture": "#5"},
"east": {"uv": [0, 0, 4, 9], "texture": "#5"},
@ -46,21 +44,6 @@
"up": {"uv": [0, 0, 4, 9], "rotation": 90, "texture": "#5"},
"down": {"uv": [0, 0, 4, 9], "rotation": 90, "texture": "#5"}
}
},
{
"name": "Axis",
"from": [6, 6, 0],
"to": [10, 10, 16],
"shade": false,
"rotation": {"angle": 0, "axis": "x", "origin": [8, 1, 8]},
"faces": {
"north": {"uv": [6, 6, 10, 10], "rotation": 180, "texture": "#1"},
"east": {"uv": [6, 0, 10, 16], "rotation": 90, "texture": "#0"},
"south": {"uv": [6, 6, 10, 10], "texture": "#1"},
"west": {"uv": [6, 0, 10, 16], "rotation": 270, "texture": "#0"},
"up": {"uv": [6, 0, 10, 16], "texture": "#0"},
"down": {"uv": [6, 0, 10, 16], "rotation": 180, "texture": "#0"}
}
}
]
}