The Bugs win

- Condensed mechanical crafting into one JEI page category, scaling down slots if necessary
- Fixed ploughs trying to break water blocks
- Fixed stationary contraptions getting nudged around by expiring farmland blocks
- Shulker boxes can now be used as portable storage on contraptions
- Added vertical rotation support to buttons, levers
- Fixed certain directional blocks flipping around inconsistently when contraptions rotate by 180 degress
- Random safety checks
- Vertical belts no longer pop when rotated horizontally
- Fixed inconsistent funnel activation when items are inserted on the same segment
- Fixed adjustable pulley popping off due to floating point precision issues
- Fixed toggle latch acting strangely with input signals
- Schematicannons can now place belts safely
- Removed invalid Schematic item from creative tab
This commit is contained in:
simibubi 2020-05-09 00:09:10 +02:00
parent 65853c9da0
commit 4cbf424f4d
22 changed files with 546 additions and 287 deletions

View file

@ -24,7 +24,6 @@ import com.simibubi.create.compat.jei.category.SawingCategory;
import com.simibubi.create.compat.jei.category.SmokingViaFanCategory;
import com.simibubi.create.compat.jei.category.SplashingCategory;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.crafter.MechanicalCraftingRecipe;
import com.simibubi.create.modules.contraptions.components.mixer.MixingRecipe;
import com.simibubi.create.modules.contraptions.components.press.MechanicalPressTileEntity;
import com.simibubi.create.modules.logistics.block.inventories.FlexcrateScreen;
@ -66,8 +65,7 @@ public class CreateJEI implements IModPlugin {
private PackingCategory packingCategory;
private PolishingCategory polishingCategory;
private MysteriousItemConversionCategory mysteryConversionCategory;
private MechanicalCraftingCategory smallMechanicalCraftingCategory;
private MechanicalCraftingCategory largeMechanicalCraftingCategory;
private MechanicalCraftingCategory mechanicalCraftingCategory;
@Override
public ResourceLocation getPluginUid() {
@ -88,8 +86,7 @@ public class CreateJEI implements IModPlugin {
packingCategory = new PackingCategory();
polishingCategory = new PolishingCategory();
mysteryConversionCategory = new MysteriousItemConversionCategory();
smallMechanicalCraftingCategory = new MechanicalCraftingCategory(false);
largeMechanicalCraftingCategory = new MechanicalCraftingCategory(true);
mechanicalCraftingCategory = new MechanicalCraftingCategory();
}
@Override
@ -99,10 +96,11 @@ public class CreateJEI implements IModPlugin {
@Override
public void registerCategories(IRecipeCategoryRegistration registration) {
registration.addRecipeCategories(millingCategory, crushingCategory, splashingCategory, pressingCategory,
smokingCategory, blastingCategory, blockzapperCategory, mixingCategory, sawingCategory,
blockCuttingCategory, packingCategory, polishingCategory, mysteryConversionCategory,
smallMechanicalCraftingCategory, largeMechanicalCraftingCategory);
registration
.addRecipeCategories(millingCategory, crushingCategory, splashingCategory, pressingCategory,
smokingCategory, blastingCategory, blockzapperCategory, mixingCategory, sawingCategory,
blockCuttingCategory, packingCategory, polishingCategory, mysteryConversionCategory,
mechanicalCraftingCategory);
}
@Override
@ -132,33 +130,28 @@ public class CreateJEI implements IModPlugin {
packingCategory.getUid());
registration.addRecipes(findRecipes(AllRecipes.SANDPAPER_POLISHING), polishingCategory.getUid());
registration.addRecipes(MysteriousItemConversionCategory.getRecipes(), mysteryConversionCategory.getUid());
registration.addRecipes(findRecipes(
r -> (r instanceof MechanicalCraftingRecipe) && MechanicalCraftingCategory.isSmall((ShapedRecipe) r)),
smallMechanicalCraftingCategory.getUid());
registration.addRecipes(
findRecipes(
r -> (r.getType() == IRecipeType.CRAFTING || r.getType() == AllRecipes.MECHANICAL_CRAFTING.type)
&& (r instanceof ShapedRecipe) && !(r instanceof MechanicalCraftingRecipe)
&& MechanicalCraftingCategory.isSmall((ShapedRecipe) r)),
smallMechanicalCraftingCategory.getUid());
registration.addRecipes(findRecipes(
r -> (r.getType() == IRecipeType.CRAFTING || r.getType() == AllRecipes.MECHANICAL_CRAFTING.type)
&& (r instanceof ShapedRecipe) && !MechanicalCraftingCategory.isSmall((ShapedRecipe) r)),
largeMechanicalCraftingCategory.getUid());
registration.addRecipes(findRecipes(r -> (r.getType() == AllRecipes.MECHANICAL_CRAFTING.type)),
mechanicalCraftingCategory.getUid());
registration.addRecipes(findRecipes(r -> (r.getType() == IRecipeType.CRAFTING
&& r.getType() != AllRecipes.MECHANICAL_CRAFTING.type) && (r instanceof ShapedRecipe)),
mechanicalCraftingCategory.getUid());
}
@Override
public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
ItemStack fan = new ItemStack(AllBlocks.ENCASED_FAN.get());
ItemStack splashingFan = fan.copy()
ItemStack splashingFan = fan
.copy()
.setDisplayName(new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.splashing.fan")));
ItemStack smokingFan = fan.copy().setDisplayName(
new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.smokingViaFan.fan")));
ItemStack blastingFan = fan.copy().setDisplayName(
new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.blastingViaFan.fan")));
ItemStack smokingFan = fan
.copy()
.setDisplayName(
new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.smokingViaFan.fan")));
ItemStack blastingFan = fan
.copy()
.setDisplayName(
new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.blastingViaFan.fan")));
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MILLSTONE.get()), millingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.CRUSHING_WHEEL.get()), crushingCategory.getUid());
@ -176,10 +169,9 @@ public class CreateJEI implements IModPlugin {
registration.addRecipeCatalyst(new ItemStack(AllBlocks.BASIN.get()), packingCategory.getUid());
registration.addRecipeCatalyst(AllItems.SAND_PAPER.asStack(), polishingCategory.getUid());
registration.addRecipeCatalyst(AllItems.RED_SAND_PAPER.asStack(), polishingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_CRAFTER.get()),
smallMechanicalCraftingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_CRAFTER.get()),
largeMechanicalCraftingCategory.getUid());
registration
.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_CRAFTER.get()),
mechanicalCraftingCategory.getUid());
}
@Override
@ -193,18 +185,30 @@ public class CreateJEI implements IModPlugin {
}
private static List<IRecipe<?>> findRecipes(Predicate<IRecipe<?>> pred) {
return Minecraft.getInstance().world.getRecipeManager().getRecipes().stream().filter(pred)
return Minecraft.getInstance().world
.getRecipeManager()
.getRecipes()
.stream()
.filter(pred)
.collect(Collectors.toList());
}
private static List<IRecipe<?>> findRecipesByType(IRecipeType<?> type) {
return Minecraft.getInstance().world.getRecipeManager().getRecipes().stream().filter(r -> r.getType() == type)
return Minecraft.getInstance().world
.getRecipeManager()
.getRecipes()
.stream()
.filter(r -> r.getType() == type)
.collect(Collectors.toList());
}
private static List<IRecipe<?>> findRecipesById(ResourceLocation id) {
return Minecraft.getInstance().world.getRecipeManager().getRecipes().stream()
.filter(r -> r.getSerializer().getRegistryName().equals(id)).collect(Collectors.toList());
return Minecraft.getInstance().world
.getRecipeManager()
.getRecipes()
.stream()
.filter(r -> r.getSerializer().getRegistryName().equals(id))
.collect(Collectors.toList());
}
private static List<IRecipe<?>> findRecipesByTypeExcluding(IRecipeType<?> type, IRecipeType<?> excludingType) {

View file

@ -1,39 +1,103 @@
package com.simibubi.create.compat.jei.category;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter;
import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredientRenderer;
import mezz.jei.api.ingredients.IIngredients;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Rarity;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.util.NonNullList;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextFormatting;
public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecipe> {
private AnimatedCrafter crafter;
private boolean large;
private final class CrafterIngredientRenderer implements IIngredientRenderer<ItemStack> {
public MechanicalCraftingCategory(boolean large) {
super("mechanical_crafting" + (large ? "_large" : ""), itemIcon(AllBlocks.MECHANICAL_CRAFTER.get()),
emptyBackground(large ? 177 : 177, large ? 235 : 81));
this.large = large;
crafter = new AnimatedCrafter(large);
private ShapedRecipe recipe;
public CrafterIngredientRenderer(ShapedRecipe recipe) {
this.recipe = recipe;
}
@Override
public void render(int xPosition, int yPosition, ItemStack ingredient) {
GlStateManager.pushMatrix();
GlStateManager.translated(xPosition, yPosition, 0);
float scale = getScale(recipe);
GlStateManager.scaled(scale, scale, scale);
if (ingredient != null) {
GlStateManager.enableDepthTest();
RenderHelper.enableGUIStandardItemLighting();
Minecraft minecraft = Minecraft.getInstance();
FontRenderer font = getFontRenderer(minecraft, ingredient);
ItemRenderer itemRenderer = minecraft.getItemRenderer();
itemRenderer.renderItemAndEffectIntoGUI(null, ingredient, 0, 0);
itemRenderer.renderItemOverlayIntoGUI(font, ingredient, 0, 0, null);
GlStateManager.disableBlend();
RenderHelper.disableStandardItemLighting();
}
GlStateManager.popMatrix();
}
@Override
public List<String> getTooltip(ItemStack ingredient, ITooltipFlag tooltipFlag) {
Minecraft minecraft = Minecraft.getInstance();
PlayerEntity player = minecraft.player;
List<String> list;
try {
list = ingredient
.getTooltip(player, tooltipFlag)
.stream()
.map(ITextComponent::getFormattedText)
.collect(Collectors.toList());
} catch (RuntimeException | LinkageError e) {
return new ArrayList<>();
}
Rarity rarity;
try {
rarity = ingredient.getRarity();
} catch (RuntimeException | LinkageError e) {
rarity = Rarity.COMMON;
}
for (int k = 0; k < list.size(); ++k) {
if (k == 0) {
list.set(k, rarity.color + list.get(k));
} else {
list.set(k, TextFormatting.GRAY + list.get(k));
}
}
return list;
}
}
public static boolean isSmall(ShapedRecipe recipe) {
return Math.max((recipe).getWidth(), (recipe).getHeight()) <= 4;
}
private AnimatedCrafter crafter = new AnimatedCrafter();
@Override
public String getTitle() {
return Lang.translate("recipe.mechanical_crafting");
public MechanicalCraftingCategory() {
super("mechanical_crafting", itemIcon(AllBlocks.MECHANICAL_CRAFTER.get()), emptyBackground(177, 107));
}
@Override
@ -47,45 +111,79 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecip
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
NonNullList<Ingredient> recipeIngredients = recipe.getIngredients();
itemStacks.init(0, false, large ? 136 : 141, large ? 196 : 50);
itemStacks.init(0, false, 133, 80);
itemStacks.set(0, recipe.getRecipeOutput().getStack());
int x = getGridX(recipe);
int y = getGridY(recipe);
int x = getXPadding(recipe);
int y = getYPadding(recipe);
float scale = getScale(recipe);
int size = recipeIngredients.size();
IIngredientRenderer<ItemStack> renderer = new CrafterIngredientRenderer(recipe);
for (int i = 0; i < size; i++) {
itemStacks.init(i + 1, true, x + (i % recipe.getWidth()) * 19, y + (i / recipe.getWidth()) * 19);
float f = 19 * scale;
int slotSize = (int) (16 * scale);
int xPosition = (int) (x + 1 + (i % recipe.getWidth()) * f);
int yPosition = (int) (y + 1 + (i / recipe.getWidth()) * f);
itemStacks.init(i + 1, true, renderer, xPosition, yPosition, slotSize, slotSize, 0, 0);
itemStacks.set(i + 1, Arrays.asList(recipeIngredients.get(i).getMatchingStacks()));
}
}
public int getGridY(ShapedRecipe recipe) {
return 3 + (int) (((large ? 9 : 4) - recipe.getRecipeHeight()) * 19 / 2f);
static int maxSize = 100;
public static float getScale(ShapedRecipe recipe) {
int w = recipe.getWidth();
int h = recipe.getHeight();
return Math.min(1, maxSize / (19f * Math.max(w, h)));
}
public int getGridX(ShapedRecipe recipe) {
return 3 + (int) (((large ? 9 : 4) - recipe.getRecipeWidth()) * 19 / 2f);
public static int getYPadding(ShapedRecipe recipe) {
return 3 + 50 - (int) (getScale(recipe) * recipe.getHeight() * 19 * .5);
}
public static int getXPadding(ShapedRecipe recipe) {
return 3 + 50 - (int) (getScale(recipe) * recipe.getWidth() * 19 * .5);
}
@Override
public void draw(ShapedRecipe recipe, double mouseX, double mouseY) {
int x = getGridX(recipe);
int y = getGridY(recipe);
GlStateManager.pushMatrix();
float scale = getScale(recipe);
GlStateManager.translated(getXPadding(recipe), getYPadding(recipe), 0);
for (int row = 0; row < recipe.getHeight(); row++)
for (int col = 0; col < recipe.getWidth(); col++)
if (!recipe.getIngredients().get(row * recipe.getWidth() + col).hasNoMatchingItems())
ScreenResources.JEI_SLOT.draw(x + col * 19, y + row * 19);
if (!recipe.getIngredients().get(row * recipe.getWidth() + col).hasNoMatchingItems()) {
GlStateManager.pushMatrix();
GlStateManager.translated((int) col * 19 * scale, (int) row * 19 * scale, 0);
GlStateManager.scaled(scale, scale, scale);
ScreenResources.JEI_SLOT.draw(0, 0);
GlStateManager.popMatrix();
}
ScreenResources.JEI_SLOT.draw(large ? 136 : 141, large ? 196 : 50);
if (large)
ScreenResources.JEI_ARROW.draw(86, 200);
else
ScreenResources.JEI_DOWN_ARROW.draw(136, 32);
GlStateManager.popMatrix();
ScreenResources.JEI_SHADOW.draw(large ? 20 : 84, large ? 223 : 68);
crafter.draw(large ? 105 : 185, large ? 189 : -1);
ScreenResources.JEI_SLOT.draw(133, 80);
ScreenResources.JEI_DOWN_ARROW.draw(128, 59);
ScreenResources.JEI_SHADOW.draw(116, 36);
crafter.draw(219, 8);
GlStateManager.pushMatrix();
GlStateManager.translated(0, 0, 200);
RenderHelper.disableStandardItemLighting();
int amount = 0;
for (Ingredient ingredient : recipe.getIngredients()) {
if (Ingredient.EMPTY == ingredient)
continue;
amount++;
}
Minecraft.getInstance().fontRenderer
.drawStringWithShadow(amount + "", 142, 39, 0xFFFFFF);
RenderHelper.enableStandardItemLighting();
GlStateManager.popMatrix();
}
@Override

View file

@ -12,12 +12,6 @@ import net.minecraft.util.Direction;
public class AnimatedCrafter extends AnimatedKinetics {
boolean four;
public AnimatedCrafter(boolean four) {
this.four = four;
}
@Override
public int getWidth() {
return 50;
@ -40,23 +34,7 @@ public class AnimatedCrafter extends AnimatedKinetics {
ScreenElementRenderer.renderModel(() -> cogwheel(true));
ScreenElementRenderer.renderBlock(this::body);
GlStateManager.translatef(0, 50, 0);
ScreenElementRenderer.renderModel(() -> cogwheel(false));
ScreenElementRenderer.renderBlock(this::body);
if (four) {
GlStateManager.translatef(50, -50, 0);
ScreenElementRenderer.renderModel(() -> cogwheel(false));
ScreenElementRenderer.renderBlock(this::body);
GlStateManager.translatef(0, 50, 0);
ScreenElementRenderer.renderModel(() -> cogwheel(true));
ScreenElementRenderer.renderBlock(this::body);
} else {
GlStateManager.translatef(0, 50, 0);
ScreenElementRenderer.renderModel(() -> cogwheel(true));
ScreenElementRenderer.renderBlock(this::body);
}
GlStateManager.translatef(50, 0, 0);
GlStateManager.popMatrix();
}
@ -71,8 +49,10 @@ public class AnimatedCrafter extends AnimatedKinetics {
}
private BlockState body() {
return AllBlocks.MECHANICAL_CRAFTER.get().getDefaultState().with(MechanicalCrafterBlock.HORIZONTAL_FACING,
Direction.WEST);
return AllBlocks.MECHANICAL_CRAFTER
.get()
.getDefaultState()
.with(MechanicalCrafterBlock.HORIZONTAL_FACING, Direction.WEST);
}
}

View file

@ -251,11 +251,6 @@ public class CreateAdvancements implements IDataProvider {
private void andesiteExpertLane(Consumer<Advancement> t, Advancement root) {
String id = Create.ID;
Advancement expert_lane_1 = advancement("expert_lane_1", Blocks.ANDESITE, TaskType.SILENT_GATE)
.withParent(root)
.withCriterion("0", itemGathered(AllBlocks.ANDESITE_CASING.get()))
.register(t, id + ":expert_lane_1");
}
// Datagen

View file

@ -248,7 +248,8 @@ public class RotationPropagator {
// Do not overpower you own network -> cycle
if (!currentTE.hasNetwork() || currentTE.network.equals(neighbourTE.network)) {
if (Math.abs(newSpeed) > Math.abs(speedOfNeighbour))
float epsilon = Math.abs(speedOfNeighbour) / 256f / 256f;
if (Math.abs(newSpeed) > Math.abs(speedOfNeighbour) + epsilon)
world.destroyBlock(pos, true);
continue;
}

View file

@ -7,6 +7,7 @@ import com.simibubi.create.modules.contraptions.components.actors.PloughBlock.Pl
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
import net.minecraft.block.BlockState;
import net.minecraft.block.FlowingFluidBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.item.Items;
@ -25,8 +26,8 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override
public boolean isActive(MovementContext context) {
return !VecHelper.isVecPointingTowards(context.relativeMotion,
context.state.get(HORIZONTAL_FACING).getOpposite());
return !VecHelper
.isVecPointingTowards(context.relativeMotion, context.state.get(HORIZONTAL_FACING).getOpposite());
}
@Override
@ -66,7 +67,8 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
return state.getCollisionShape(world, breakingPos).isEmpty();
return state.getCollisionShape(world, breakingPos).isEmpty()
&& !(state.getBlock() instanceof FlowingFluidBlock);
}
@Override

View file

@ -298,11 +298,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
BearingContraption bc = (BearingContraption) getContraption();
Direction facing = bc.getFacing();
Vec3d activeAreaOffset = actor.getActiveAreaOffset(context);
if (activeAreaOffset.mul(VecHelper.planeByNormal(new Vec3d(facing.getDirectionVec())))
if (activeAreaOffset
.mul(VecHelper.planeByNormal(new Vec3d(facing.getDirectionVec())))
.equals(Vec3d.ZERO)) {
if (VecHelper.onSameAxis(blockInfo.pos, BlockPos.ZERO, facing.getAxis())) {
context.motion = new Vec3d(facing.getDirectionVec()).scale(
facing.getAxis().getCoordinate(roll - prevRoll, yaw - prevYaw, pitch - prevPitch));
context.motion = new Vec3d(facing.getDirectionVec())
.scale(facing
.getAxis()
.getCoordinate(roll - prevRoll, yaw - prevYaw, pitch - prevPitch));
context.relativeMotion = context.motion;
int timer = context.data.getInt("StationaryTimer");
if (timer > 0) {
@ -333,8 +336,9 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
setMotion(Vec3d.ZERO);
if (getController() != null)
getController().onStall();
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
new ContraptionStallPacket(getEntityId(), posX, posY, posZ, yaw, pitch, roll));
AllPackets.channel
.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
new ContraptionStallPacket(getEntityId(), posX, posY, posZ, yaw, pitch, roll));
}
dataManager.set(STALLED, contraption.stalled);
} else {
@ -463,8 +467,9 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
if (contraption != null)
compound.put("Contraption", contraption.writeNBT());
if (!stationary && motionBeforeStall != null)
compound.put("CachedMotion",
newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z));
compound
.put("CachedMotion",
newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z));
if (controllerPos != null)
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
if (forcedAngle != -1)
@ -542,8 +547,9 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
}
if (horizontalMag(vec3d1) > horizontalMag(vec3d)) {
vec3d = vec3d1.add(collideBoundingBoxHeuristically(e, new Vec3d(0.0D, -vec3d1.y + vec.y, 0.0D),
axisalignedbb.offset(vec3d1), e.world, iselectioncontext, reuseablestream));
vec3d = vec3d1
.add(collideBoundingBoxHeuristically(e, new Vec3d(0.0D, -vec3d1.y + vec.y, 0.0D),
axisalignedbb.offset(vec3d1), e.world, iselectioncontext, reuseablestream));
}
}
@ -593,6 +599,12 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
// Make sure nothing can move contraptions out of the way
public void setMotion(Vec3d motionIn) {}
@Override
public void setPositionAndUpdate(double x, double y, double z) {
if (!stationary)
super.setPositionAndUpdate(x, y, z);
}
@Override
public PushReaction getPushReaction() {
return PushReaction.IGNORE;

View file

@ -9,6 +9,7 @@ import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.ChestType;
import net.minecraft.tileentity.BarrelTileEntity;
import net.minecraft.tileentity.ChestTileEntity;
import net.minecraft.tileentity.ShulkerBoxTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraftforge.items.CapabilityItemHandler;
@ -107,6 +108,8 @@ public class MountedStorage {
TileEntityType<?> type = te.getType();
if (type == AllTileEntities.FLEXCRATE.type)
return true;
if (te instanceof ShulkerBoxTileEntity)
return true;
if (te instanceof ChestTileEntity)
return true;
if (te instanceof BarrelTileEntity)

View file

@ -1,7 +1,9 @@
package com.simibubi.create.modules.contraptions.components.contraptions;
import static net.minecraft.block.HorizontalFaceBlock.FACE;
import static net.minecraft.state.properties.BlockStateProperties.AXIS;
import static net.minecraft.state.properties.BlockStateProperties.FACING;
import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.VecHelper;
@ -10,10 +12,13 @@ import com.simibubi.create.modules.contraptions.components.contraptions.chassis.
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.HorizontalFaceBlock;
import net.minecraft.block.SlabBlock;
import net.minecraft.block.StairsBlock;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.properties.AttachFace;
import net.minecraft.state.properties.Half;
import net.minecraft.state.properties.SlabType;
import net.minecraft.util.Direction;
@ -73,90 +78,133 @@ public class StructureTransform {
* horizontal axes
*/
public BlockState apply(BlockState state) {
if (rotationAxis == Axis.Y)
state = state.rotate(rotation);
else {
if (state.getBlock() instanceof AbstractChassisBlock)
return rotateChassis(state);
return state.rotate(rotation);
if (state.getBlock() instanceof StairsBlock) {
if (state.get(StairsBlock.FACING).getAxis() != rotationAxis) {
for (int i = 0; i < rotation.ordinal(); i++) {
Direction direction = state.get(StairsBlock.FACING);
Half half = state.get(StairsBlock.HALF);
if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ half == Half.BOTTOM
^ direction.getAxis() == Axis.Z)
state = state.cycle(StairsBlock.HALF);
else
state = state.with(StairsBlock.FACING, direction.getOpposite());
}
} else {
if (rotation == Rotation.CLOCKWISE_180) {
state = state.cycle(StairsBlock.HALF);
}
}
Block block = state.getBlock();
if (block instanceof AbstractChassisBlock)
return rotateChassis(state);
if (block instanceof HorizontalFaceBlock) {
Direction stateFacing = state.get(HorizontalFaceBlock.HORIZONTAL_FACING);
AttachFace stateFace = state.get(FACE);
Direction forcedAxis = rotationAxis == Axis.Z ? Direction.EAST : Direction.SOUTH;
if (stateFacing.getAxis() == rotationAxis && stateFace == AttachFace.WALL)
return state;
for (int i = 0; i < rotation.ordinal(); i++) {
stateFace = state.get(FACE);
stateFacing = state.get(HorizontalFaceBlock.HORIZONTAL_FACING);
boolean b = state.get(FACE) == AttachFace.CEILING;
state = state.with(HORIZONTAL_FACING, b ? forcedAxis : forcedAxis.getOpposite());
if (stateFace != AttachFace.WALL) {
state = state.with(FACE, AttachFace.WALL);
continue;
}
if (stateFacing.getAxisDirection() == AxisDirection.POSITIVE) {
state = state.with(FACE, AttachFace.FLOOR);
continue;
}
state = state.with(FACE, AttachFace.CEILING);
}
if (AllBlocks.BELT.typeOf(state)) {
if (state.get(BeltBlock.HORIZONTAL_FACING).getAxis() != rotationAxis) {
for (int i = 0; i < rotation.ordinal(); i++) {
Slope slope = state.get(BeltBlock.SLOPE);
Direction direction = state.get(BeltBlock.HORIZONTAL_FACING);
return state;
}
// Rotate diagonal
if (slope != Slope.HORIZONTAL && slope != Slope.VERTICAL) {
if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ slope == Slope.DOWNWARD
^ direction.getAxis() == Axis.Z) {
state =
state.with(BeltBlock.SLOPE, slope == Slope.UPWARD ? Slope.DOWNWARD : Slope.UPWARD);
} else {
state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite());
}
if (block instanceof StairsBlock) {
if (state.get(StairsBlock.FACING).getAxis() != rotationAxis) {
for (int i = 0; i < rotation.ordinal(); i++) {
Direction direction = state.get(StairsBlock.FACING);
Half half = state.get(StairsBlock.HALF);
if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ half == Half.BOTTOM
^ direction.getAxis() == Axis.Z)
state = state.cycle(StairsBlock.HALF);
else
state = state.with(StairsBlock.FACING, direction.getOpposite());
}
} else {
if (rotation == Rotation.CLOCKWISE_180) {
state = state.cycle(StairsBlock.HALF);
}
}
return state;
}
// Rotate horizontal/vertical
if (AllBlocks.BELT.typeOf(state)) {
if (state.get(BeltBlock.HORIZONTAL_FACING).getAxis() != rotationAxis) {
for (int i = 0; i < rotation.ordinal(); i++) {
Slope slope = state.get(BeltBlock.SLOPE);
Direction direction = state.get(BeltBlock.HORIZONTAL_FACING);
// Rotate diagonal
if (slope != Slope.HORIZONTAL && slope != Slope.VERTICAL) {
if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ slope == Slope.DOWNWARD
^ direction.getAxis() == Axis.Z) {
state = state.with(BeltBlock.SLOPE, slope == Slope.UPWARD ? Slope.DOWNWARD : Slope.UPWARD);
} else {
if (slope == Slope.HORIZONTAL ^ direction.getAxis() == Axis.Z) {
state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite());
}
state = state.with(BeltBlock.SLOPE,
slope == Slope.HORIZONTAL ? Slope.VERTICAL : Slope.HORIZONTAL);
}
}
} else {
if (rotation == Rotation.CLOCKWISE_180) {
Slope slope = state.get(BeltBlock.SLOPE);
Direction direction = state.get(BeltBlock.HORIZONTAL_FACING);
if (slope == Slope.UPWARD || slope == Slope.DOWNWARD) {
state = state.with(BeltBlock.SLOPE, slope == Slope.UPWARD ? Slope.DOWNWARD
: slope == Slope.DOWNWARD ? Slope.UPWARD : slope);
} else if (slope == Slope.VERTICAL) {
state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite());
}
// Rotate horizontal/vertical
} else {
if (slope == Slope.HORIZONTAL ^ direction.getAxis() == Axis.Z) {
state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite());
}
state =
state.with(BeltBlock.SLOPE, slope == Slope.HORIZONTAL ? Slope.VERTICAL : Slope.HORIZONTAL);
}
}
} else {
if (rotation == Rotation.CLOCKWISE_180) {
Slope slope = state.get(BeltBlock.SLOPE);
Direction direction = state.get(BeltBlock.HORIZONTAL_FACING);
if (slope == Slope.UPWARD || slope == Slope.DOWNWARD) {
state = state
.with(BeltBlock.SLOPE, slope == Slope.UPWARD ? Slope.DOWNWARD
: slope == Slope.DOWNWARD ? Slope.UPWARD : slope);
} else if (slope == Slope.VERTICAL) {
state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite());
}
}
return state;
}
return state;
}
if (state.has(FACING)) {
Direction newFacing = transformFacing(state.get(FACING));
if (state.has(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE)) {
if (rotationAxis == newFacing.getAxis() && rotation.ordinal() % 2 == 1)
state = state.cycle(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE);
}
state = state.with(FACING, newFacing);
} else if (state.has(AXIS)) {
state = state.with(AXIS, transformAxis(state.get(AXIS)));
} else if (rotation == Rotation.CLOCKWISE_180) {
if (state.has(FACING)) {
Direction newFacing = transformFacing(state.get(FACING));
if (state.has(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE)) {
if (rotationAxis == newFacing.getAxis() && rotation.ordinal() % 2 == 1)
state = state.cycle(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE);
}
state = state.with(FACING, newFacing);
} else if (state.has(AXIS)) {
state = state.with(AXIS, transformAxis(state.get(AXIS)));
} else if (rotation == Rotation.CLOCKWISE_180) {
state = state.rotate(rotation);
if (state.has(SlabBlock.TYPE) && state.get(SlabBlock.TYPE) != SlabType.DOUBLE)
state = state.with(SlabBlock.TYPE,
state.get(SlabBlock.TYPE) == SlabType.BOTTOM ? SlabType.TOP : SlabType.BOTTOM);
Direction stateFacing = state.get(FACING);
if (stateFacing.getAxis() == rotationAxis)
return state;
}
if (state.has(HORIZONTAL_FACING)) {
Direction stateFacing = state.get(HORIZONTAL_FACING);
if (stateFacing.getAxis() == rotationAxis)
return state;
}
state = state.rotate(rotation);
if (state.has(SlabBlock.TYPE) && state.get(SlabBlock.TYPE) != SlabType.DOUBLE)
state = state
.with(SlabBlock.TYPE,
state.get(SlabBlock.TYPE) == SlabType.BOTTOM ? SlabType.TOP : SlabType.BOTTOM);
}
return state;

View file

@ -51,8 +51,11 @@ import net.minecraftforge.items.ItemHandlerHelper;
public class DeployerTileEntity extends KineticTileEntity {
private static final List<Pair<BlockPos, Direction>> EXTRACTING_LOCATIONS = Arrays.asList(Direction.values())
.stream().map(d -> Pair.of(BlockPos.ZERO.offset(d), d.getOpposite())).collect(Collectors.toList());
private static final List<Pair<BlockPos, Direction>> EXTRACTING_LOCATIONS = Arrays
.asList(Direction.values())
.stream()
.map(d -> Pair.of(BlockPos.ZERO.offset(d), d.getOpposite()))
.collect(Collectors.toList());
private FilteringBehaviour filtering;
private ExtractingBehaviour extracting;
@ -373,8 +376,9 @@ public class DeployerTileEntity extends KineticTileEntity {
reach = tag.getFloat("Reach");
if (tag.contains("Particle")) {
ItemStack particleStack = ItemStack.read(tag.getCompound("Particle"));
SandPaperItem.spawnParticles(VecHelper.getCenterOf(pos).add(getMovementVector().scale(2f)), particleStack,
this.world);
SandPaperItem
.spawnParticles(VecHelper.getCenterOf(pos).add(getMovementVector().scale(2f)), particleStack,
this.world);
}
super.readClientUpdate(tag);
@ -402,7 +406,8 @@ public class DeployerTileEntity extends KineticTileEntity {
@Override
public void remove() {
super.remove();
invHandler.invalidate();
if (invHandler != null)
invHandler.invalidate();
}
public void changeMode() {

View file

@ -50,6 +50,7 @@ import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.Hand;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.MathHelper;
@ -59,6 +60,7 @@ import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import net.minecraft.world.WorldType;
import net.minecraft.world.storage.loot.LootParameters;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@ -342,10 +344,11 @@ public class BeltBlock extends HorizontalKineticBlock
double d7 = d4 * d1 + x1;
double d8 = d5 * d2 + y1;
double d9 = d6 * d3 + z1;
manager.addEffect(
(new DiggingParticle(world, (double) pos.getX() + d7, (double) pos.getY() + d8,
(double) pos.getZ() + d9, d4 - 0.5D, d5 - 0.5D, d6 - 0.5D, state))
.setBlockPos(pos));
manager
.addEffect(
(new DiggingParticle(world, (double) pos.getX() + d7, (double) pos.getY() + d8,
(double) pos.getZ() + d9, d4 - 0.5D, d5 - 0.5D, d6 - 0.5D, state))
.setBlockPos(pos));
}
}
}
@ -397,7 +400,7 @@ public class BeltBlock extends HorizontalKineticBlock
}
public static void initBelt(World world, BlockPos pos) {
if (world.isRemote)
if (world.isRemote || world.getWorldType() == WorldType.DEBUG_ALL_BLOCK_STATES)
return;
BlockState state = world.getBlockState(pos);
@ -430,7 +433,9 @@ public class BeltBlock extends HorizontalKineticBlock
for (BlockPos beltPos : beltChain) {
TileEntity tileEntity = world.getTileEntity(beltPos);
if (tileEntity instanceof BeltTileEntity) {
BlockState currentState = world.getBlockState(beltPos);
if (tileEntity instanceof BeltTileEntity && AllBlocks.BELT.typeOf(currentState)) {
BeltTileEntity te = (BeltTileEntity) tileEntity;
te.setController(currentPos);
te.beltLength = beltChain.size();
@ -439,7 +444,6 @@ public class BeltBlock extends HorizontalKineticBlock
te.markDirty();
te.sendData();
BlockState currentState = world.getBlockState(beltPos);
boolean isVertical = currentState.get(BeltBlock.SLOPE) == Slope.VERTICAL;
if (currentState.get(CASING) && isVertical) {
@ -540,10 +544,10 @@ public class BeltBlock extends HorizontalKineticBlock
int limit = 1000;
BlockPos current = controllerPos;
while (limit-- > 0 && current != null) {
positions.add(current);
BlockState state = world.getBlockState(current);
if (!AllBlocks.BELT.typeOf(state))
break;
positions.add(current);
current = nextSegmentPosition(state, current, true);
}
@ -607,7 +611,7 @@ public class BeltBlock extends HorizontalKineticBlock
public Class<BeltTileEntity> getTileEntityClass() {
return BeltTileEntity.class;
}
@Override
public ItemRequirement getRequiredItems(BlockState state) {
List<ItemStack> required = new ArrayList<>();
@ -622,4 +626,20 @@ public class BeltBlock extends HorizontalKineticBlock
return new ItemRequirement(ItemUseType.CONSUME, required);
}
@Override
public BlockState rotate(BlockState state, Rotation rot) {
BlockState rotate = super.rotate(state, rot);
if (state.get(SLOPE) != Slope.VERTICAL)
return rotate;
if (state.get(HORIZONTAL_FACING).getAxisDirection() != rotate.get(HORIZONTAL_FACING).getAxisDirection()) {
if (state.get(PART) == Part.START)
return rotate.with(PART, Part.END);
if (state.get(PART) == Part.END)
return rotate.with(PART, Part.START);
}
return rotate;
}
}

View file

@ -73,6 +73,8 @@ public class BeltTileEntity extends KineticTileEntity {
// Init belt
if (beltLength == 0)
BeltBlock.initBelt(world, pos);
if (!AllBlocks.BELT.typeOf(world.getBlockState(pos)))
return;
// Initialize Belt Attachments
if (world != null && trackerUpdateTag != null) {
@ -306,8 +308,8 @@ public class BeltTileEntity extends KineticTileEntity {
public Direction getMovementFacing() {
Axis axis = getBeltFacing().getAxis();
return Direction.getFacingFromAxisDirection(axis,
getBeltMovementSpeed() < 0 ^ axis == Axis.X ? NEGATIVE : POSITIVE);
return Direction
.getFacingFromAxisDirection(axis, getBeltMovementSpeed() < 0 ^ axis == Axis.X ? NEGATIVE : POSITIVE);
}
protected Direction getBeltFacing() {
@ -344,7 +346,7 @@ public class BeltTileEntity extends KineticTileEntity {
if (simulate)
return true;
transportedStack.beltPosition = index + .5f - Math.signum(getSpeed()) / 16f;
transportedStack.beltPosition = index + .5f - Math.signum(getDirectionAwareBeltMovementSpeed()) / 16f;
Direction movementFacing = getMovementFacing();
if (!side.getAxis().isVertical()) {

View file

@ -92,15 +92,16 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther {
return ActionResultType.SUCCESS;
}
private void createBelts(World world, BlockPos start, BlockPos end) {
public static void createBelts(World world, BlockPos start, BlockPos end) {
BeltBlock.Slope slope = getSlopeBetween(start, end);
Direction facing = getFacingFromTo(start, end);
BlockPos diff = end.subtract(start);
if (diff.getX() == diff.getZ())
facing = Direction.getFacingFromAxis(facing.getAxisDirection(),
world.getBlockState(start).get(BlockStateProperties.AXIS) == Axis.X ? Axis.Z : Axis.X);
facing = Direction
.getFacingFromAxis(facing.getAxisDirection(),
world.getBlockState(start).get(BlockStateProperties.AXIS) == Axis.X ? Axis.Z : Axis.X);
List<BlockPos> beltsToCreate = getBeltChainBetween(start, end, slope, facing);
BlockState beltBlock = AllBlocks.BELT.get().getDefaultState();
@ -110,12 +111,17 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther {
boolean pulley = AllBlocks.SHAFT.typeOf(world.getBlockState(pos));
if (part == Part.MIDDLE && pulley)
part = Part.PULLEY;
world.setBlockState(pos, beltBlock.with(BeltBlock.SLOPE, slope).with(BeltBlock.PART, part)
.with(BeltBlock.HORIZONTAL_FACING, facing), 3);
world
.setBlockState(pos,
beltBlock
.with(BeltBlock.SLOPE, slope)
.with(BeltBlock.PART, part)
.with(BeltBlock.HORIZONTAL_FACING, facing),
3);
}
}
private Direction getFacingFromTo(BlockPos start, BlockPos end) {
private static Direction getFacingFromTo(BlockPos start, BlockPos end) {
Axis beltAxis = start.getX() == end.getX() ? Axis.Z : Axis.X;
BlockPos diff = end.subtract(start);
AxisDirection axisDirection = AxisDirection.POSITIVE;
@ -129,7 +135,7 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther {
return Direction.getFacingFromAxis(axisDirection, beltAxis);
}
private Slope getSlopeBetween(BlockPos start, BlockPos end) {
private static Slope getSlopeBetween(BlockPos start, BlockPos end) {
BlockPos diff = end.subtract(start);
if (diff.getY() != 0) {
@ -140,7 +146,7 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther {
return Slope.HORIZONTAL;
}
private List<BlockPos> getBeltChainBetween(BlockPos start, BlockPos end, Slope slope, Direction direction) {
private static List<BlockPos> getBeltChainBetween(BlockPos start, BlockPos end, Slope slope, Direction direction) {
List<BlockPos> positions = new LinkedList<>();
int limit = 1000;
BlockPos current = start;

View file

@ -118,18 +118,18 @@ public class BeltInventory {
float diffToEnd = beltMovementPositive ? belt.beltLength - currentPos : -currentPos;
float limitedMovement =
beltMovementPositive ? Math.min(movement, diffToEnd) : Math.max(movement, diffToEnd);
float nextOffset = current.beltPosition + limitedMovement;
if (!onClient) {
if (!onClient && segmentBefore != -1) {
// Don't move if belt attachments want to continue processing
if (segmentBefore != -1 && current.locked) {
if (current.locked) {
BeltTileEntity beltSegment = BeltHelper.getBeltAtSegment(belt, segmentBefore);
if (beltSegment != null) {
// wait in case belt isnt initialized yet
if (current.locked && beltSegment.trackerUpdateTag != null)
continue;
current.locked = false;
List<BeltAttachmentState> attachments = beltSegment.attachmentTracker.attachments;
for (BeltAttachmentState attachmentState : attachments) {
@ -146,22 +146,24 @@ public class BeltInventory {
}
// See if any new belt processing catches the item
int upcomingSegment = (int) (current.beltPosition + (beltMovementPositive ? .5f : -.5f));
for (int segment = upcomingSegment; beltMovementPositive ? segment + .5f <= nextOffset
: segment + .5f >= nextOffset; segment += beltMovementPositive ? 1 : -1) {
BeltTileEntity beltSegment = BeltHelper.getBeltAtSegment(belt, segmentBefore);
if (beltSegment == null)
break;
for (BeltAttachmentState attachmentState : beltSegment.attachmentTracker.attachments) {
ItemStack stackBefore = current.stack.copy();
if (attachmentState.attachment.startProcessingItem(beltSegment, current, attachmentState)) {
current.beltPosition = segment + .5f + (beltMovementPositive ? 1 / 64f : -1 / 64f);
current.locked = true;
belt.sendData();
continue Items;
if (current.beltPosition > .5f || beltMovementPositive) {
int firstUpcomingSegment = (int) (current.beltPosition + (beltMovementPositive ? .5f : -.5f));
for (int segment = firstUpcomingSegment; beltMovementPositive ? segment + .5f <= nextOffset
: segment + .5f >= nextOffset; segment += beltMovementPositive ? 1 : -1) {
BeltTileEntity beltSegment = BeltHelper.getBeltAtSegment(belt, segment);
if (beltSegment == null)
break;
for (BeltAttachmentState attachmentState : beltSegment.attachmentTracker.attachments) {
ItemStack stackBefore = current.stack.copy();
if (attachmentState.attachment.startProcessingItem(beltSegment, current, attachmentState)) {
current.beltPosition = segment + .5f + (beltMovementPositive ? 1 / 64f : -1 / 64f);
current.locked = true;
belt.sendData();
continue Items;
}
if (!stackBefore.equals(current.stack, true))
belt.sendData();
}
if (!stackBefore.equals(current.stack, true))
belt.sendData();
}
}
}
@ -202,8 +204,9 @@ public class BeltInventory {
if (segment == -1)
continue;
if (!world.isRemote)
world.updateComparatorOutputLevel(BeltHelper.getPositionForOffset(belt, segment),
belt.getBlockState().getBlock());
world
.updateComparatorOutputLevel(BeltHelper.getPositionForOffset(belt, segment),
belt.getBlockState().getBlock());
}
}
@ -392,7 +395,8 @@ public class BeltInventory {
public void read(CompoundNBT nbt) {
getItems().clear();
nbt.getList("Items", NBT.TAG_COMPOUND)
nbt
.getList("Items", NBT.TAG_COMPOUND)
.forEach(inbt -> getItems().add(TransportedItemStack.read((CompoundNBT) inbt)));
beltMovementPositive = nbt.getBoolean("PositiveOrder");
}

View file

@ -33,6 +33,8 @@ public class AdjustablePulleyTileEntity extends KineticTileEntity {
}
public void neighborChanged() {
if (!hasWorld())
return;
int power = world.getRedstonePowerFromNeighbors(pos);
if (power != signal)
signalChanged = true;

View file

@ -117,7 +117,9 @@ public class StockswitchTileEntity extends SyncedTileEntity {
if (!invState.hasTileEntity())
return false;
TileEntity invTE = world.getTileEntity(invPos);
if (invTE == null)
return false;
observedInventory = invTE.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
if (observedInventory.isPresent()) {
updateCurrentLevel();

View file

@ -4,6 +4,8 @@ import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.RedstoneWireBlock;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.Direction;
@ -28,13 +30,9 @@ public class LatchBlock extends ToggleLatchBlock {
@Override
protected void updateState(World worldIn, BlockPos pos, BlockState state) {
boolean back = state.get(POWERED);
boolean shouldBack = this.shouldBePowered(worldIn, pos, state);
boolean shouldBack = shouldBePowered(worldIn, pos, state);
boolean side = state.get(POWERED_SIDE);
Direction direction = state.get(HORIZONTAL_FACING);
Direction left = direction.rotateY();
Direction right = direction.rotateYCCW();
boolean shouldSide = worldIn.isSidePowered(pos, left) || worldIn.isSidePowered(pos, right);
boolean shouldSide = isPoweredOnSides(worldIn, pos, state);
TickPriority tickpriority = TickPriority.HIGH;
if (this.isFacingTowardsRepeater(worldIn, pos, state))
@ -48,16 +46,28 @@ public class LatchBlock extends ToggleLatchBlock {
worldIn.getPendingBlockTicks().scheduleTick(pos, this, this.getDelay(state), tickpriority);
}
protected boolean isPoweredOnSides(World worldIn, BlockPos pos, BlockState state) {
Direction direction = state.get(HORIZONTAL_FACING);
Direction left = direction.rotateY();
Direction right = direction.rotateYCCW();
for (Direction d : new Direction[] { left, right }) {
BlockPos blockpos = pos.offset(d);
int i = worldIn.getRedstonePower(blockpos, d);
if (i > 0)
return true;
BlockState blockstate = worldIn.getBlockState(blockpos);
return blockstate.getBlock() == Blocks.REDSTONE_WIRE ? blockstate.get(RedstoneWireBlock.POWER) > 0 : false;
}
return false;
}
@Override
public void tick(BlockState state, World worldIn, BlockPos pos, Random random) {
boolean back = state.get(POWERED);
boolean shouldBack = this.shouldBePowered(worldIn, pos, state);
boolean side = state.get(POWERED_SIDE);
Direction direction = state.get(HORIZONTAL_FACING);
Direction left = direction.rotateY();
Direction right = direction.rotateYCCW();
boolean shouldSide = worldIn.isBlockPowered(pos.offset(left)) || worldIn.isBlockPowered(pos.offset(right));
boolean shouldSide = isPoweredOnSides(worldIn, pos, state);
BlockState stateIn = state;
if (back != shouldBack) {

View file

@ -93,7 +93,7 @@ public class FlexcrateTileEntity extends CrateTileEntity implements INamedContai
return getOtherCrate();
return this;
}
public void onSplit() {
FlexcrateTileEntity other = getOtherCrate();
if (other == null)
@ -181,7 +181,7 @@ public class FlexcrateTileEntity extends CrateTileEntity implements INamedContai
public <T> LazyOptional<T> getCapability(Capability<T> capability, Direction facing) {
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
FlexcrateTileEntity mainCrate = getMainCrate();
if (mainCrate != null && mainCrate.invHandler.isPresent())
if (mainCrate != null && mainCrate.invHandler != null && mainCrate.invHandler.isPresent())
return mainCrate.invHandler.cast();
}
return super.getCapability(capability, facing);

View file

@ -2,6 +2,12 @@ package com.simibubi.create.modules.schematics.block;
import java.util.Optional;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.item.BeltConnectorItem;
import com.simibubi.create.modules.contraptions.relays.elementary.ShaftBlock;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
@ -9,6 +15,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
@ -28,8 +35,7 @@ public abstract class LaunchedItem {
return (int) (Math.max(10, MathHelper.sqrt(MathHelper.sqrt(target.distanceSq(start))) * 4f));
}
LaunchedItem() {
}
LaunchedItem() {}
private LaunchedItem(BlockPos target, ItemStack stack, int ticksLeft, int total) {
this.target = target;
@ -60,8 +66,8 @@ public abstract class LaunchedItem {
}
public static LaunchedItem fromNBT(CompoundNBT c) {
LaunchedItem launched =
c.contains("BlockState") ? new LaunchedItem.ForBlockState() : new LaunchedItem.ForEntity();
LaunchedItem launched = c.contains("Length") ? new LaunchedItem.ForBelt()
: c.contains("BlockState") ? new LaunchedItem.ForBlockState() : new LaunchedItem.ForEntity();
launched.readNBT(c);
return launched;
}
@ -78,8 +84,7 @@ public abstract class LaunchedItem {
public static class ForBlockState extends LaunchedItem {
public BlockState state;
ForBlockState() {
}
ForBlockState() {}
public ForBlockState(BlockPos start, BlockPos target, ItemStack stack, BlockState state) {
super(start, target, stack);
@ -105,18 +110,59 @@ public abstract class LaunchedItem {
if (state.has(BlockStateProperties.EXTENDED))
state = state.with(BlockStateProperties.EXTENDED, false);
if (AllBlocks.BELT.typeOf(state)) {
world.setBlockState(target, state, 2);
return;
}
world.setBlockState(target, state, 18);
state.getBlock().onBlockPlacedBy(world, target, state, null, stack);
}
}
public static class ForBelt extends ForBlockState {
public int length;
public ForBelt() {}
@Override
public CompoundNBT serializeNBT() {
CompoundNBT serializeNBT = super.serializeNBT();
serializeNBT.putInt("Length", length);
return serializeNBT;
}
@Override
void readNBT(CompoundNBT nbt) {
length = nbt.getInt("Length");
super.readNBT(nbt);
}
public ForBelt(BlockPos start, BlockPos target, ItemStack stack, BlockState state, int length) {
super(start, target, stack, state);
this.length = length;
}
@Override
void place(World world) {
// todo place belt
boolean isStart = state.get(BeltBlock.PART) == Part.START;
BlockPos offset = BeltBlock.nextSegmentPosition(state, BlockPos.ZERO, isStart);
int i = length - 1;
Axis axis = state.get(BeltBlock.HORIZONTAL_FACING).rotateY().getAxis();
world.setBlockState(target, AllBlocks.SHAFT.getDefault().with(ShaftBlock.AXIS, axis));
BeltConnectorItem
.createBelts(world, target, target.add(offset.getX() * i, offset.getY() * i, offset.getZ() * i));
}
}
public static class ForEntity extends LaunchedItem {
public Entity entity;
private CompoundNBT deferredTag;
ForEntity() {
}
ForEntity() {}
public ForEntity(BlockPos start, BlockPos target, ItemStack stack, Entity entity) {
super(start, target, stack);

View file

@ -13,6 +13,11 @@ import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.elementary.ShaftBlock;
import com.simibubi.create.modules.schematics.ItemRequirement;
import com.simibubi.create.modules.schematics.ItemRequirement.ItemUseType;
import com.simibubi.create.modules.schematics.MaterialChecklist;
@ -41,11 +46,13 @@ import net.minecraft.state.properties.DoubleBlockHalf;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.gen.feature.template.PlacementSettings;
import net.minecraft.world.gen.feature.template.Template;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@ -456,7 +463,14 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
ItemStack icon = requirement.isEmpty() || requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0);
if (entityMode)
launchEntity(target, icon, blockReader.getEntities().get(printingEntityIndex));
else
else if (AllBlocks.BELT.typeOf(blockState)) {
TileEntity te = blockReader.getTileEntity(currentPos.add(schematicAnchor));
blockState = stripBeltIfNotLast(blockState);
if (te instanceof BeltTileEntity && AllBlocks.BELT.typeOf(blockState))
launchBelt(target, blockState, ((BeltTileEntity) te).beltLength);
else
launchBlock(target, icon, blockState);
} else
launchBlock(target, icon, blockState);
printerCooldown = config().schematicannonDelay.get();
@ -465,6 +479,33 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
missingItem = null;
}
public BlockState stripBeltIfNotLast(BlockState blockState) {
// is highest belt?
boolean isLastSegment = false;
Direction facing = blockState.get(BeltBlock.HORIZONTAL_FACING);
Slope slope = blockState.get(BeltBlock.SLOPE);
boolean positive = facing.getAxisDirection() == AxisDirection.POSITIVE;
boolean start = blockState.get(BeltBlock.PART) == Part.START;
boolean end = blockState.get(BeltBlock.PART) == Part.END;
switch (slope) {
case DOWNWARD:
isLastSegment = start;
break;
case UPWARD:
isLastSegment = end;
break;
case HORIZONTAL:
case VERTICAL:
default:
isLastSegment = positive && end || !positive && start;
}
if (!isLastSegment)
blockState = (blockState.get(BeltBlock.PART) == Part.MIDDLE) ? Blocks.AIR.getDefaultState()
: AllBlocks.SHAFT.getDefault().with(ShaftBlock.AXIS, facing.rotateY().getAxis());
return blockState;
}
public double getFuelUsageRate() {
return hasCreativeCrate ? 0 : config().schematicannonFuelUsage.get() / 100f;
}
@ -504,7 +545,8 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
schematicAnchor = anchor;
blockReader = new SchematicWorld(schematicAnchor, world);
activeTemplate.addBlocksToWorld(blockReader, schematicAnchor, SchematicItem.getSettings(blueprint));
PlacementSettings settings = SchematicItem.getSettings(blueprint);
activeTemplate.addBlocksToWorld(blockReader, schematicAnchor, settings);
schematicLoaded = true;
state = State.PAUSED;
statusMsg = "ready";
@ -766,6 +808,13 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
sendUpdate = true;
}
protected void launchBelt(BlockPos target, BlockState state, int length) {
blocksPlaced++;
ItemStack connector = AllItems.BELT_CONNECTOR.asStack();
flyingBlocks.add(new LaunchedItem.ForBelt(this.getPos(), target, connector, state, length));
playFiringSound();
}
protected void launchBlock(BlockPos target, ItemStack stack, BlockState state) {
if (state.getBlock() != Blocks.AIR)
blocksPlaced++;

View file

@ -17,6 +17,7 @@ import com.simibubi.create.modules.schematics.client.SchematicEditScreen;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.nbt.CompoundNBT;
@ -26,6 +27,7 @@ import net.minecraft.util.ActionResult;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
import net.minecraft.util.Mirror;
import net.minecraft.util.NonNullList;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
@ -61,6 +63,9 @@ public class SchematicItem extends Item {
return blueprint;
}
@Override
public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> items) {}
@Override
@OnlyIn(value = Dist.CLIENT)
public void addInformation(ItemStack stack, World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {

View file

@ -1,35 +0,0 @@
{
"parent": "create:andesite_casing",
"display": {
"icon": {
"item": "minecraft:andesite"
},
"title": {
"translate": "advancement.create.expert_lane_1"
},
"description": {
"translate": "advancement.create.expert_lane_1.desc"
},
"frame": "challenge",
"show_toast": false,
"announce_to_chat": false,
"hidden": false
},
"criteria": {
"0": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"item": "create:andesite_casing"
}
]
}
}
},
"requirements": [
[
"0"
]
]
}