mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-18 07:53:07 +01:00
Portable Funnels & Extractors
- Fixed custom sword not having a sweeping effect - Fixed invalid kinetic tileentity state when dimension is being unloaded - Mechanical harvesters now interact with kelp blocks - Extractors and Funnels are now portable and have special movement traits #117 - Fixed false positives on having reached the block movement limit for contraptions - Fixed self-modification within a belt's update cycle, addresses #116 - Fixed belt processing not re-activating segement attachments, addresses #132 - Fixed reversing components (gearbox, gearshift) breaking when a new source overpowers the network - Reduced attack damage of the Deforester - Fixed redstone links not being powered by wires consistently #106 - New entries for attribute filters: Washable, Smeltable, Smokable and Smeltable in Blast furnace - Fixed redstone links behaving inconsistently when unloaded and reloaded - Bumped oldest supported forge version
This commit is contained in:
parent
b885a60003
commit
e891aeb8c1
31 changed files with 345 additions and 78 deletions
|
@ -4,7 +4,6 @@ import static com.simibubi.create.foundation.item.AllToolTypes.AXE;
|
|||
import static com.simibubi.create.foundation.item.AllToolTypes.HOE;
|
||||
import static com.simibubi.create.foundation.item.AllToolTypes.PICKAXE;
|
||||
import static com.simibubi.create.foundation.item.AllToolTypes.SHOVEL;
|
||||
import static com.simibubi.create.foundation.item.AllToolTypes.SWORD;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -21,6 +20,7 @@ import com.simibubi.create.modules.curiosities.RefinedRadianceItem;
|
|||
import com.simibubi.create.modules.curiosities.ShadowSteelItem;
|
||||
import com.simibubi.create.modules.curiosities.deforester.DeforesterItem;
|
||||
import com.simibubi.create.modules.curiosities.symmetry.SymmetryWandItem;
|
||||
import com.simibubi.create.modules.curiosities.tools.AllToolTiers;
|
||||
import com.simibubi.create.modules.curiosities.tools.BlazingToolItem;
|
||||
import com.simibubi.create.modules.curiosities.tools.RoseQuartzToolItem;
|
||||
import com.simibubi.create.modules.curiosities.tools.SandPaperItem;
|
||||
|
@ -39,6 +39,7 @@ import net.minecraft.item.Item;
|
|||
import net.minecraft.item.Item.Properties;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Rarity;
|
||||
import net.minecraft.item.SwordItem;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.event.RegistryEvent;
|
||||
|
@ -113,16 +114,16 @@ public enum AllItems {
|
|||
BLAZING_PICKAXE(p -> new BlazingToolItem(1, -2.8F, p, PICKAXE)),
|
||||
BLAZING_SHOVEL(p -> new BlazingToolItem(1.5F, -3.0F, p, SHOVEL)),
|
||||
BLAZING_AXE(p -> new BlazingToolItem(5.0F, -3.0F, p, AXE)),
|
||||
BLAZING_SWORD(p -> new BlazingToolItem(3, -2.4F, p, SWORD)),
|
||||
BLAZING_SWORD(p -> new SwordItem(AllToolTiers.BLAZING, 3, -2.4F, p)),
|
||||
|
||||
ROSE_QUARTZ_PICKAXE(p -> new RoseQuartzToolItem(1, -2.8F, p, PICKAXE)),
|
||||
ROSE_QUARTZ_SHOVEL(p -> new RoseQuartzToolItem(1.5F, -3.0F, p, SHOVEL)),
|
||||
ROSE_QUARTZ_AXE(p -> new RoseQuartzToolItem(5.0F, -3.0F, p, AXE)),
|
||||
ROSE_QUARTZ_SWORD(p -> new RoseQuartzToolItem(3, -2.4F, p, SWORD)),
|
||||
ROSE_QUARTZ_SWORD(p -> new SwordItem(AllToolTiers.ROSE_QUARTZ, 3, -2.4F, p)),
|
||||
|
||||
SHADOW_STEEL_PICKAXE(p -> new ShadowSteelToolItem(2.5F, -2.0F, p, PICKAXE)),
|
||||
SHADOW_STEEL_MATTOCK(p -> new ShadowSteelToolItem(2.5F, -1.5F, p, SHOVEL, AXE, HOE)),
|
||||
SHADOW_STEEL_SWORD(p -> new ShadowSteelToolItem(3, -2.0F, p, SWORD)),
|
||||
SHADOW_STEEL_SWORD(p -> new SwordItem(AllToolTiers.SHADOW_STEEL, 3, -2.0F, p)),
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ public class FilteringBehaviour extends TileEntityBehaviour {
|
|||
}
|
||||
|
||||
public boolean test(ItemStack stack) {
|
||||
return filter.isEmpty() || FilterItem.test(stack, filter);
|
||||
return filter.isEmpty() || FilterItem.test(tileEntity.getWorld(), stack, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -61,7 +61,7 @@ public class KineticNetwork {
|
|||
if (te.isSource())
|
||||
sources.put(te, te.getAddedStressCapacity());
|
||||
members.put(te, te.getStressApplied());
|
||||
te.updateStressFromNetwork(currentCapacity, currentStress);
|
||||
te.updateFromNetwork(currentCapacity, currentStress, getSize());
|
||||
te.networkDirty = true;
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ public class KineticNetwork {
|
|||
if (te.isSource())
|
||||
sources.remove(te);
|
||||
members.remove(te);
|
||||
te.updateStressFromNetwork(0, 0);
|
||||
te.updateFromNetwork(0, 0, 0);
|
||||
|
||||
if (members.isEmpty()) {
|
||||
TorquePropagator.networks.get(te.getWorld()).remove(this.id);
|
||||
|
@ -93,7 +93,7 @@ public class KineticNetwork {
|
|||
|
||||
public void sync() {
|
||||
for (KineticTileEntity te : members.keySet())
|
||||
te.updateStressFromNetwork(currentCapacity, currentStress);
|
||||
te.updateFromNetwork(currentCapacity, currentStress, getSize());
|
||||
}
|
||||
|
||||
public void updateCapacity() {
|
||||
|
|
|
@ -123,7 +123,8 @@ public class RotationPropagator {
|
|||
if (isLargeGearToSpeedController(stateTo, stateFrom, diff))
|
||||
return SpeedControllerTileEntity.getConveyedSpeed(to, from, false);
|
||||
|
||||
return from.getTheoreticalSpeed() * getRotationSpeedModifier(from, to);
|
||||
float rotationSpeedModifier = getRotationSpeedModifier(from, to);
|
||||
return from.getTheoreticalSpeed() * rotationSpeedModifier;
|
||||
}
|
||||
|
||||
private static boolean isLargeToLargeGear(BlockState from, BlockState to, BlockPos diff) {
|
||||
|
@ -233,8 +234,8 @@ public class RotationPropagator {
|
|||
// Neighbour faster, overpower the incoming tree
|
||||
if (Math.abs(oppositeSpeed) > Math.abs(speedOfCurrent)) {
|
||||
float prevSpeed = currentTE.getSpeed();
|
||||
currentTE.setSpeed(oppositeSpeed);
|
||||
currentTE.setSource(neighbourTE.getPos());
|
||||
currentTE.setSpeed(getConveyedSpeed(neighbourTE, currentTE));
|
||||
currentTE.onSpeedChanged(prevSpeed);
|
||||
currentTE.sendData();
|
||||
|
||||
|
@ -256,8 +257,8 @@ public class RotationPropagator {
|
|||
currentTE.removeSource();
|
||||
|
||||
float prevSpeed = neighbourTE.getSpeed();
|
||||
neighbourTE.setSpeed(newSpeed);
|
||||
neighbourTE.setSource(currentTE.getPos());
|
||||
neighbourTE.setSpeed(getConveyedSpeed(currentTE, neighbourTE));
|
||||
neighbourTE.onSpeedChanged(prevSpeed);
|
||||
neighbourTE.sendData();
|
||||
propagateNewSource(neighbourTE);
|
||||
|
|
|
@ -120,10 +120,11 @@ public abstract class KineticTileEntity extends SmartTileEntity
|
|||
}
|
||||
}
|
||||
|
||||
public void updateStressFromNetwork(float maxStress, float currentStress) {
|
||||
public void updateFromNetwork(float maxStress, float currentStress, int networkSize) {
|
||||
networkDirty = false;
|
||||
this.capacity = maxStress;
|
||||
this.stress = currentStress;
|
||||
this.networkSize = networkSize;
|
||||
boolean overStressed = maxStress < currentStress && StressImpact.isEnabled();
|
||||
|
||||
if (overStressed != this.overStressed) {
|
||||
|
@ -182,7 +183,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
|
|||
networkTag.putLong("Id", this.network);
|
||||
networkTag.putFloat("Stress", stress);
|
||||
networkTag.putFloat("Capacity", capacity);
|
||||
networkTag.putInt("Size", getOrCreateNetwork().getSize());
|
||||
networkTag.putInt("Size", networkSize);
|
||||
|
||||
float stressApplied = getStressApplied();
|
||||
float addedStressCapacity = getAddedStressCapacity();
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.simibubi.create.modules.contraptions.components.contraptions.Movement
|
|||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.CropsBlock;
|
||||
import net.minecraft.block.KelpBlock;
|
||||
import net.minecraft.block.SugarCaneBlock;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.state.IProperty;
|
||||
|
@ -111,6 +112,8 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (state.getBlock() instanceof KelpBlock)
|
||||
return true;
|
||||
if (state.getBlock() instanceof IPlantable)
|
||||
return true;
|
||||
}
|
||||
|
@ -124,7 +127,9 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
|
|||
return crop.withAge(0);
|
||||
}
|
||||
if (state.getBlock() == Blocks.SUGAR_CANE) {
|
||||
return Blocks.AIR.getDefaultState();
|
||||
if (state.getFluidState().isEmpty())
|
||||
return Blocks.AIR.getDefaultState();
|
||||
return state.getFluidState().getBlockState();
|
||||
}
|
||||
if (state.getCollisionShape(world, pos).isEmpty()) {
|
||||
for (IProperty<?> property : state.getProperties()) {
|
||||
|
@ -136,7 +141,9 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
|
|||
}
|
||||
}
|
||||
|
||||
return Blocks.AIR.getDefaultState();
|
||||
if (state.getFluidState().isEmpty())
|
||||
return Blocks.AIR.getDefaultState();
|
||||
return state.getFluidState().getBlockState();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ import com.simibubi.create.AllBlocks;
|
|||
import com.simibubi.create.modules.contraptions.components.actors.HarvesterBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.actors.PortableStorageInterfaceBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock;
|
||||
import com.simibubi.create.modules.logistics.block.belts.AttachedLogisticalBlock;
|
||||
import com.simibubi.create.modules.logistics.block.belts.FunnelBlock;
|
||||
import com.simibubi.create.modules.logistics.block.extractor.ExtractorBlock;
|
||||
import com.simibubi.create.modules.logistics.block.transposer.TransposerBlock;
|
||||
|
||||
import net.minecraft.block.AbstractPressurePlateBlock;
|
||||
import net.minecraft.block.AbstractRailBlock;
|
||||
|
@ -11,6 +15,7 @@ import net.minecraft.block.Block;
|
|||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.DoorBlock;
|
||||
import net.minecraft.block.FenceGateBlock;
|
||||
import net.minecraft.block.FlowerPotBlock;
|
||||
import net.minecraft.block.HorizontalFaceBlock;
|
||||
import net.minecraft.block.LadderBlock;
|
||||
|
@ -32,6 +37,8 @@ public class BlockMovementTraits {
|
|||
BlockState state = world.getBlockState(pos);
|
||||
if (isBrittle(state))
|
||||
return true;
|
||||
if (state.getBlock() instanceof FenceGateBlock)
|
||||
return true;
|
||||
if (state.getMaterial().isReplaceable())
|
||||
return false;
|
||||
if (state.getCollisionShape(world, pos).isEmpty())
|
||||
|
@ -41,14 +48,19 @@ public class BlockMovementTraits {
|
|||
|
||||
public static boolean movementAllowed(World world, BlockPos pos) {
|
||||
BlockState blockState = world.getBlockState(pos);
|
||||
if (blockState.getBlock() instanceof AbstractChassisBlock)
|
||||
Block block = blockState.getBlock();
|
||||
if (block instanceof AbstractChassisBlock)
|
||||
return true;
|
||||
if (blockState.getBlockHardness(world, pos) == -1)
|
||||
return false;
|
||||
if (blockState.getBlock() == Blocks.OBSIDIAN)
|
||||
if (block == Blocks.OBSIDIAN)
|
||||
return false;
|
||||
if (AllBlocks.BELT.typeOf(blockState))
|
||||
return true;
|
||||
if (block instanceof ExtractorBlock)
|
||||
return true;
|
||||
if (block instanceof FunnelBlock)
|
||||
return true;
|
||||
return blockState.getPushReaction() != PushReaction.BLOCK;
|
||||
}
|
||||
|
||||
|
@ -62,6 +74,10 @@ public class BlockMovementTraits {
|
|||
return true;
|
||||
if (block instanceof LadderBlock)
|
||||
return true;
|
||||
if (block instanceof ExtractorBlock)
|
||||
return true;
|
||||
if (block instanceof FunnelBlock)
|
||||
return true;
|
||||
if (block instanceof TorchBlock)
|
||||
return true;
|
||||
if (block instanceof FlowerPotBlock)
|
||||
|
@ -94,6 +110,8 @@ public class BlockMovementTraits {
|
|||
return direction == Direction.DOWN;
|
||||
if (block instanceof DoorBlock)
|
||||
return direction == Direction.DOWN;
|
||||
if (block instanceof AttachedLogisticalBlock && !(block instanceof TransposerBlock))
|
||||
return direction == AttachedLogisticalBlock.getBlockFacing(state);
|
||||
if (block instanceof FlowerPotBlock)
|
||||
return direction == Direction.DOWN;
|
||||
if (block instanceof RedstoneDiodeBlock)
|
||||
|
|
|
@ -114,9 +114,7 @@ public abstract class Contraption {
|
|||
frontier.add(pos);
|
||||
if (!addToInitialFrontier(world, pos, forcedDirection, frontier))
|
||||
return false;
|
||||
|
||||
Integer blockLimit = AllConfigs.SERVER.kinetics.maxBlocksMoved.get();
|
||||
for (int limit = blockLimit; limit > 0; limit--) {
|
||||
for (int limit = 100000; limit > 0; limit--) {
|
||||
if (frontier.isEmpty())
|
||||
return true;
|
||||
if (!moveBlock(world, frontier.remove(0), forcedDirection, frontier, visited))
|
||||
|
@ -183,6 +181,8 @@ public abstract class Contraption {
|
|||
}
|
||||
|
||||
add(pos, capture(world, pos));
|
||||
if (blocks.size() > AllConfigs.SERVER.kinetics.maxBlocksMoved.get())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
|||
|
||||
@Override
|
||||
public float getInterpolatedAngle(float partialTicks) {
|
||||
if (movedContraption == null || movedContraption.isStalled())
|
||||
if (movedContraption == null || movedContraption.isStalled() || !running)
|
||||
partialTicks = 0;
|
||||
return MathHelper.lerp(partialTicks, angle, angle + getAngularSpeed());
|
||||
}
|
||||
|
|
|
@ -104,8 +104,9 @@ public class DeployerMovementBehaviour extends MovementBehaviour {
|
|||
if (player == null)
|
||||
return;
|
||||
if (player.getHeldItemMainhand().isEmpty()) {
|
||||
ItemStack filter = getFilter(context);
|
||||
ItemStack held = ItemHelper.extract(context.contraption.inventory,
|
||||
stack -> FilterItem.test(stack, getFilter(context)), 1, false);
|
||||
stack -> FilterItem.test(context.world, stack, filter), 1, false);
|
||||
player.setHeldItem(Hand.MAIN_HAND, held);
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +124,8 @@ public class DeployerMovementBehaviour extends MovementBehaviour {
|
|||
if (itemstack.isEmpty())
|
||||
continue;
|
||||
|
||||
if (list == inv.mainInventory && i == inv.currentItem && FilterItem.test(itemstack, filter))
|
||||
if (list == inv.mainInventory && i == inv.currentItem
|
||||
&& FilterItem.test(context.world, itemstack, filter))
|
||||
continue;
|
||||
|
||||
dropItem(context, itemstack);
|
||||
|
|
|
@ -37,12 +37,14 @@ public class BeltInventory {
|
|||
|
||||
final BeltTileEntity belt;
|
||||
final List<TransportedItemStack> items;
|
||||
final List<TransportedItemStack> toInsert;
|
||||
boolean beltMovementPositive;
|
||||
final float SEGMENT_WINDOW = .75f;
|
||||
|
||||
public BeltInventory(BeltTileEntity te) {
|
||||
this.belt = te;
|
||||
items = new LinkedList<>();
|
||||
toInsert = new LinkedList<>();
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
|
@ -54,6 +56,14 @@ public class BeltInventory {
|
|||
belt.markDirty();
|
||||
belt.sendData();
|
||||
}
|
||||
|
||||
// Add items from previous cycle
|
||||
if (!toInsert.isEmpty()) {
|
||||
toInsert.forEach(this::insert);
|
||||
toInsert.clear();
|
||||
belt.markDirty();
|
||||
belt.sendData();
|
||||
}
|
||||
|
||||
// Assuming the first entry is furthest on the belt
|
||||
TransportedItemStack stackInFront = null;
|
||||
|
@ -325,18 +335,29 @@ public class BeltInventory {
|
|||
else if (!beltMovementPositive)
|
||||
segmentPos += 1f;
|
||||
|
||||
for (TransportedItemStack stack : items) {
|
||||
float currentPos = stack.beltPosition;
|
||||
|
||||
if (stack.insertedAt == segment && stack.insertedFrom == side
|
||||
&& (beltMovementPositive ? currentPos <= segmentPos + 1 : currentPos >= segmentPos - 1))
|
||||
for (TransportedItemStack stack : items)
|
||||
if (isBlocking(segment, side, segmentPos, stack))
|
||||
return false;
|
||||
|
||||
}
|
||||
for (TransportedItemStack stack : toInsert)
|
||||
if (isBlocking(segment, side, segmentPos, stack))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void insert(TransportedItemStack newStack) {
|
||||
private boolean isBlocking(int segment, Direction side, float segmentPos, TransportedItemStack stack) {
|
||||
float currentPos = stack.beltPosition;
|
||||
if (stack.insertedAt == segment && stack.insertedFrom == side
|
||||
&& (beltMovementPositive ? currentPos <= segmentPos + 1 : currentPos >= segmentPos - 1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addItem(TransportedItemStack newStack) {
|
||||
toInsert.add(newStack);
|
||||
}
|
||||
|
||||
private void insert(TransportedItemStack newStack) {
|
||||
if (items.isEmpty())
|
||||
items.add(newStack);
|
||||
else {
|
||||
|
|
|
@ -347,7 +347,7 @@ public class BeltTileEntity extends KineticTileEntity {
|
|||
transportedStack.insertedAt = index;
|
||||
transportedStack.insertedFrom = side;
|
||||
transportedStack.prevBeltPosition = transportedStack.beltPosition;
|
||||
nextInventory.insert(transportedStack);
|
||||
nextInventory.addItem(transportedStack);
|
||||
nextBeltController.markDirty();
|
||||
nextBeltController.sendData();
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ public class ItemHandlerBeltSegment implements IItemHandler {
|
|||
newStack.insertedAt = offset;
|
||||
newStack.beltPosition = offset + .5f + (beltInventory.beltMovementPositive ? -1 : 1) / 16f;
|
||||
newStack.prevBeltPosition = newStack.beltPosition;
|
||||
this.beltInventory.insert(newStack);
|
||||
this.beltInventory.addItem(newStack);
|
||||
this.beltInventory.belt.markDirty();
|
||||
this.beltInventory.belt.sendData();
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ public class StressGaugeTileEntity extends GaugeTileEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateStressFromNetwork(float maxStress, float currentStress) {
|
||||
super.updateStressFromNetwork(maxStress, currentStress);
|
||||
public void updateFromNetwork(float maxStress, float currentStress, int networkSize) {
|
||||
super.updateFromNetwork(maxStress, currentStress, networkSize);
|
||||
|
||||
if (!StressImpact.isEnabled())
|
||||
dialTarget = 0;
|
||||
|
@ -51,7 +51,8 @@ public class StressGaugeTileEntity extends GaugeTileEntity {
|
|||
markDirty();
|
||||
return;
|
||||
}
|
||||
updateStressFromNetwork(capacity, stress);
|
||||
|
||||
updateFromNetwork(capacity, stress, getOrCreateNetwork().getSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,7 +68,8 @@ public class StressGaugeTileEntity extends GaugeTileEntity {
|
|||
tooltip.add(spacing + TextFormatting.GRAY + Lang.translate("gui.stress_gauge.title"));
|
||||
|
||||
if (getTheoreticalSpeed() == 0)
|
||||
tooltip.add(TextFormatting.DARK_GRAY + ItemDescription.makeProgressBar(3, -1) + Lang.translate("gui.stress_gauge.no_rotation"));
|
||||
tooltip.add(TextFormatting.DARK_GRAY + ItemDescription.makeProgressBar(3, -1)
|
||||
+ Lang.translate("gui.stress_gauge.no_rotation"));
|
||||
else {
|
||||
tooltip.add(spacing + StressImpact.getFormattedStressText(stressFraction));
|
||||
|
||||
|
@ -76,10 +78,13 @@ public class StressGaugeTileEntity extends GaugeTileEntity {
|
|||
double remainingCapacity = capacity - getNetworkStress();
|
||||
double remainingCapacityAtBase = remainingCapacity / Math.abs(getTheoreticalSpeed());
|
||||
|
||||
String capacityString = spacing + StressImpact.of(stressFraction).getRelativeColor() + "%s" + Lang.translate("generic.unit.stress") + " " + TextFormatting.DARK_GRAY + "%s";
|
||||
String capacityString = spacing + StressImpact.of(stressFraction).getRelativeColor() + "%s"
|
||||
+ Lang.translate("generic.unit.stress") + " " + TextFormatting.DARK_GRAY + "%s";
|
||||
|
||||
tooltip.add(String.format(capacityString, IHaveGoggleInformation.format(remainingCapacityAtBase), Lang.translate("gui.goggles.base_value")));
|
||||
tooltip.add(String.format(capacityString, IHaveGoggleInformation.format(remainingCapacity), Lang.translate("gui.goggles.at_current_speed")));
|
||||
tooltip.add(String.format(capacityString, IHaveGoggleInformation.format(remainingCapacityAtBase),
|
||||
Lang.translate("gui.goggles.base_value")));
|
||||
tooltip.add(String.format(capacityString, IHaveGoggleInformation.format(remainingCapacity),
|
||||
Lang.translate("gui.goggles.at_current_speed")));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
|
|||
public class DeforesterItem extends AxeItem implements IHaveCustomItemModel {
|
||||
|
||||
public DeforesterItem(Properties builder) {
|
||||
super(AllToolTiers.RADIANT, 10.0F, -3.1F, builder);
|
||||
super(AllToolTiers.RADIANT, 5.0F, -3.1F, builder);
|
||||
}
|
||||
|
||||
// Moved away from Item#onBlockDestroyed as it does not get called in Creative
|
||||
|
|
|
@ -67,12 +67,16 @@ public class BlazingToolItem extends AbstractToolItem {
|
|||
public void modifyDrops(Collection<ItemStack> drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) {
|
||||
super.modifyDrops(drops, world, pos, tool, state);
|
||||
World worldIn = world.getWorld();
|
||||
helperFurnace.setWorld(worldIn);
|
||||
|
||||
RecipeManager recipeManager = worldIn.getRecipeManager();
|
||||
int enchantmentLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, tool);
|
||||
if (state == null)
|
||||
enchantmentLevel = 0;
|
||||
List<ItemStack> smeltedStacks = smeltDrops(drops, worldIn, enchantmentLevel);
|
||||
drops.addAll(smeltedStacks);
|
||||
}
|
||||
|
||||
public static List<ItemStack> smeltDrops(Collection<ItemStack> drops, World worldIn, int enchantmentLevel) {
|
||||
helperFurnace.setWorld(worldIn);
|
||||
RecipeManager recipeManager = worldIn.getRecipeManager();
|
||||
List<ItemStack> smeltedStacks = new ArrayList<>();
|
||||
Iterator<ItemStack> dropper = drops.iterator();
|
||||
while (dropper.hasNext()) {
|
||||
|
@ -87,13 +91,12 @@ public class BlazingToolItem extends AbstractToolItem {
|
|||
|
||||
float modifier = 1;
|
||||
if (stack.getItem() instanceof BlockItem && !(out.getItem() instanceof BlockItem))
|
||||
modifier += world.getRandom().nextFloat() * enchantmentLevel;
|
||||
modifier += worldIn.getRandom().nextFloat() * enchantmentLevel;
|
||||
|
||||
out.setCount((int) (out.getCount() * modifier + .4f));
|
||||
smeltedStacks.addAll(ItemHelper.multipliedOutput(stack, out));
|
||||
}
|
||||
|
||||
drops.addAll(smeltedStacks);
|
||||
return smeltedStacks;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -113,7 +113,12 @@ public class SandPaperItem extends Item implements IHaveCustomItemModel {
|
|||
public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) {
|
||||
return enchantment == Enchantments.FORTUNE || super.canApplyAtEnchantingTable(stack, enchantment);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getItemEnchantability(ItemStack stack) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack onItemUseFinish(ItemStack stack, World worldIn, LivingEntity entityLiving) {
|
||||
if (!(entityLiving instanceof PlayerEntity))
|
||||
|
|
|
@ -16,8 +16,10 @@ import net.minecraft.entity.Entity;
|
|||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.item.IItemTier;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.TieredItem;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.EntityDamageSource;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
@ -98,8 +100,11 @@ public class ToolEvents {
|
|||
ItemStack heldItemMainhand = player.getHeldItemMainhand();
|
||||
String marker = "create_roseQuartzRange";
|
||||
CompoundNBT persistentData = player.getPersistentData();
|
||||
Item item = heldItemMainhand.getItem();
|
||||
boolean holdingRoseQuartz =
|
||||
item instanceof TieredItem && ((TieredItem) item).getTier() == AllToolTiers.ROSE_QUARTZ;
|
||||
|
||||
if (!(heldItemMainhand.getItem() instanceof RoseQuartzToolItem)) {
|
||||
if (!holdingRoseQuartz) {
|
||||
if (persistentData.contains(marker)) {
|
||||
player.getAttributes().removeAttributeModifiers(RoseQuartzToolItem.rangeModifier);
|
||||
persistentData.remove(marker);
|
||||
|
@ -127,18 +132,20 @@ public class ToolEvents {
|
|||
PlayerEntity player = (PlayerEntity) trueSource;
|
||||
ItemStack heldItemMainhand = player.getHeldItemMainhand();
|
||||
Item item = heldItemMainhand.getItem();
|
||||
IItemTier tier = item instanceof TieredItem ? ((TieredItem) item).getTier() : null;
|
||||
|
||||
if (item instanceof ShadowSteelToolItem)
|
||||
if (tier == AllToolTiers.SHADOW_STEEL)
|
||||
event.setCanceled(true);
|
||||
|
||||
if (item instanceof BlazingToolItem) {
|
||||
BlazingToolItem blazingToolItem = (BlazingToolItem) item;
|
||||
if (tier == AllToolTiers.BLAZING) {
|
||||
List<ItemStack> drops = event.getDrops().stream().map(entity -> {
|
||||
ItemStack stack = entity.getItem();
|
||||
entity.remove();
|
||||
return stack;
|
||||
}).collect(Collectors.toList());
|
||||
blazingToolItem.modifyDrops(drops, world, player.getPosition(), heldItemMainhand, null);
|
||||
|
||||
drops = BlazingToolItem.smeltDrops(drops, world, 0);
|
||||
|
||||
event.getDrops().clear();
|
||||
drops.stream().map(stack -> {
|
||||
ItemEntity entity = new ItemEntity(world, target.posX, target.posY, target.posZ, stack);
|
||||
|
@ -156,7 +163,10 @@ public class ToolEvents {
|
|||
if (attackingPlayer == null)
|
||||
return;
|
||||
ItemStack heldItemMainhand = attackingPlayer.getHeldItemMainhand();
|
||||
if (heldItemMainhand.getItem() instanceof ShadowSteelToolItem) {
|
||||
Item item = heldItemMainhand.getItem();
|
||||
IItemTier tier = item instanceof TieredItem ? ((TieredItem) item).getTier() : null;
|
||||
|
||||
if (tier == AllToolTiers.SHADOW_STEEL) {
|
||||
int level = EnchantmentHelper.getEnchantmentLevel(Enchantments.LOOTING, heldItemMainhand);
|
||||
float modifier = 1 + event.getEntity().world.getRandom().nextFloat() * level;
|
||||
event.setDroppedExperience((int) (event.getDroppedExperience() * modifier + .4f));
|
||||
|
|
|
@ -58,7 +58,7 @@ public class InWorldProcessing {
|
|||
public static Type byBlock(IBlockReader reader, BlockPos pos) {
|
||||
BlockState blockState = reader.getBlockState(pos);
|
||||
IFluidState fluidState = reader.getFluidState(pos);
|
||||
if (fluidState.getFluid() == Fluids.WATER)
|
||||
if (fluidState.getFluid() == Fluids.WATER || fluidState.getFluid() == Fluids.FLOWING_WATER)
|
||||
return Type.SPLASHING;
|
||||
if (blockState.getBlock() == Blocks.FIRE
|
||||
|| (blockState.getBlock() == Blocks.CAMPFIRE && blockState.get(CampfireBlock.LIT)))
|
||||
|
@ -103,16 +103,19 @@ public class InWorldProcessing {
|
|||
return recipe.isPresent();
|
||||
}
|
||||
|
||||
if (type == Type.SPLASHING) {
|
||||
splashingInv.setInventorySlotContents(0, stack);
|
||||
Optional<SplashingRecipe> recipe =
|
||||
world.getRecipeManager().getRecipe(AllRecipes.SPLASHING.getType(), splashingInv, world);
|
||||
return recipe.isPresent();
|
||||
}
|
||||
if (type == Type.SPLASHING)
|
||||
return isWashable(stack, world);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isWashable(ItemStack stack, World world) {
|
||||
splashingInv.setInventorySlotContents(0, stack);
|
||||
Optional<SplashingRecipe> recipe =
|
||||
world.getRecipeManager().getRecipe(AllRecipes.SPLASHING.getType(), splashingInv, world);
|
||||
return recipe.isPresent();
|
||||
}
|
||||
|
||||
public static void applyProcessing(ItemEntity entity, Type type) {
|
||||
if (decrementProcessingTime(entity, type) != 0)
|
||||
return;
|
||||
|
@ -152,6 +155,8 @@ public class InWorldProcessing {
|
|||
List<TransportedItemStack> transportedStacks = new ArrayList<>();
|
||||
for (ItemStack additional : stacks) {
|
||||
TransportedItemStack newTransported = transported.getSimilar();
|
||||
newTransported.beltPosition -= Math.signum(belt.getDirectionAwareBeltMovementSpeed()) * 1/32f;
|
||||
newTransported.prevBeltPosition = newTransported.beltPosition;
|
||||
newTransported.stack = additional.copy();
|
||||
transportedStacks.add(newTransported);
|
||||
}
|
||||
|
@ -279,7 +284,7 @@ public class InWorldProcessing {
|
|||
public static void spawnParticlesForProcessing(World world, Vec3d vec, Type type) {
|
||||
if (!world.isRemote)
|
||||
return;
|
||||
if (world.rand.nextInt(4) != 0)
|
||||
if (world.rand.nextInt(8) != 0)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
|
|
|
@ -93,6 +93,10 @@ public class RedstoneLinkNetworkHandler {
|
|||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
if (actor.getWorld().getTileEntity(other.tileEntity.getPos()) != other.tileEntity) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
if (!withinRange(actor, other))
|
||||
continue;
|
||||
if (other.isTransmitting()) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.simibubi.create.modules.logistics.block;
|
|||
|
||||
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
||||
import com.simibubi.create.foundation.utility.AllShapes;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -61,6 +62,12 @@ public class RedstoneLinkBlock extends ProperDirectionalBlock {
|
|||
return;
|
||||
|
||||
boolean shouldPower = worldIn.getWorld().isBlockPowered(pos);
|
||||
|
||||
for (Direction direction : Iterate.directions) {
|
||||
BlockPos blockpos = pos.offset(direction);
|
||||
shouldPower |= worldIn.getRedstonePower(blockpos, Direction.UP) > 0;
|
||||
}
|
||||
|
||||
boolean previouslyPowered = state.get(POWERED);
|
||||
|
||||
if (previouslyPowered != shouldPower) {
|
||||
|
@ -134,7 +141,7 @@ public class RedstoneLinkBlock extends ProperDirectionalBlock {
|
|||
|
||||
@Override
|
||||
public boolean canConnectRedstone(BlockState state, IBlockReader world, BlockPos pos, Direction side) {
|
||||
return state.get(FACING) == Direction.UP && side != null;
|
||||
return side != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,6 +9,8 @@ import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
|
|||
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
|
||||
import com.simibubi.create.foundation.block.IWithTileEntity;
|
||||
import com.simibubi.create.foundation.utility.AllShapes;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
|
||||
|
@ -34,9 +36,10 @@ import net.minecraft.world.IBlockReader;
|
|||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class FunnelBlock extends AttachedLogisticalBlock implements IBeltAttachment, IWithTileEntity<FunnelTileEntity> {
|
||||
public class FunnelBlock extends AttachedLogisticalBlock implements IBeltAttachment, IWithTileEntity<FunnelTileEntity>, IPortableBlock {
|
||||
|
||||
public static final BooleanProperty BELT = BooleanProperty.create("belt");
|
||||
public static final MovementBehaviour MOVEMENT = new FunnelMovementBehaviour();
|
||||
|
||||
@Override
|
||||
protected void fillStateContainer(Builder<Block, BlockState> builder) {
|
||||
|
@ -211,4 +214,9 @@ public class FunnelBlock extends AttachedLogisticalBlock implements IBeltAttachm
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MovementBehaviour getMovementBehaviour() {
|
||||
return MOVEMENT;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package com.simibubi.create.modules.logistics.block.belts;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterItem;
|
||||
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
|
||||
public class FunnelMovementBehaviour extends MovementBehaviour {
|
||||
|
||||
@Override
|
||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||
super.visitNewPosition(context, pos);
|
||||
|
||||
World world = context.world;
|
||||
List<ItemEntity> items = world.getEntitiesWithinAABB(ItemEntity.class, new AxisAlignedBB(pos));
|
||||
ItemStack filter = getFilter(context);
|
||||
|
||||
for (ItemEntity item : items) {
|
||||
ItemStack toInsert = item.getItem();
|
||||
if (!filter.isEmpty() && !FilterItem.test(context.world, toInsert, filter))
|
||||
continue;
|
||||
ItemStack remainder = ItemHandlerHelper.insertItemStacked(context.contraption.inventory, toInsert, false);
|
||||
if (remainder.getCount() == toInsert.getCount())
|
||||
continue;
|
||||
if (remainder.isEmpty()) {
|
||||
item.setItem(ItemStack.EMPTY);
|
||||
item.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
item.setItem(remainder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private ItemStack getFilter(MovementContext context) {
|
||||
return ItemStack.read(context.tileData.getCompound("Filter"));
|
||||
}
|
||||
|
||||
}
|
|
@ -4,6 +4,8 @@ import com.simibubi.create.AllBlocks;
|
|||
import com.simibubi.create.foundation.utility.AllShapes;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||
import com.simibubi.create.modules.logistics.block.belts.AttachedLogisticalBlock;
|
||||
import com.simibubi.create.modules.logistics.block.belts.BeltAttachableLogisticalBlock;
|
||||
|
||||
|
@ -22,9 +24,10 @@ import net.minecraft.util.math.shapes.VoxelShape;
|
|||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ExtractorBlock extends BeltAttachableLogisticalBlock {
|
||||
public class ExtractorBlock extends BeltAttachableLogisticalBlock implements IPortableBlock {
|
||||
|
||||
public static BooleanProperty POWERED = BlockStateProperties.POWERED;
|
||||
private static final MovementBehaviour MOVEMENT = new ExtractorMovementBehaviour();
|
||||
|
||||
public ExtractorBlock() {
|
||||
super();
|
||||
|
@ -119,4 +122,9 @@ public class ExtractorBlock extends BeltAttachableLogisticalBlock {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MovementBehaviour getMovementBehaviour() {
|
||||
return MOVEMENT;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package com.simibubi.create.modules.logistics.block.extractor;
|
||||
|
||||
import com.simibubi.create.foundation.item.ItemHelper;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||
import com.simibubi.create.modules.logistics.block.belts.AttachedLogisticalBlock;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterItem;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvents;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ExtractorMovementBehaviour extends MovementBehaviour {
|
||||
|
||||
@Override
|
||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||
super.visitNewPosition(context, pos);
|
||||
|
||||
World world = context.world;
|
||||
VoxelShape collisionShape = world.getBlockState(pos).getCollisionShape(world, pos);
|
||||
if (!collisionShape.isEmpty())
|
||||
return;
|
||||
if (!world.getEntitiesWithinAABB(ItemEntity.class, new AxisAlignedBB(pos)).isEmpty())
|
||||
return;
|
||||
|
||||
ItemStack filter = getFilter(context);
|
||||
int amount = getFilterAmount(context);
|
||||
ItemStack dropped = ItemHelper.extract(context.contraption.inventory,
|
||||
stack -> FilterItem.test(context.world, stack, filter), amount == 0 ? -1 : amount, false);
|
||||
|
||||
if (dropped.isEmpty())
|
||||
return;
|
||||
if (world.isRemote)
|
||||
return;
|
||||
|
||||
Vec3d entityPos = VecHelper.getCenterOf(pos).add(0, -0.5f, 0);
|
||||
Entity entityIn = null;
|
||||
Direction facing = AttachedLogisticalBlock.getBlockFacing(context.state);
|
||||
if (facing == Direction.DOWN)
|
||||
entityPos = entityPos.add(0, .5, 0);
|
||||
|
||||
entityIn = new ItemEntity(world, entityPos.x, entityPos.y, entityPos.z, dropped);
|
||||
entityIn.setMotion(Vec3d.ZERO);
|
||||
((ItemEntity) entityIn).setPickupDelay(5);
|
||||
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, 1/16f, .1f);
|
||||
world.addEntity(entityIn);
|
||||
}
|
||||
|
||||
private ItemStack getFilter(MovementContext context) {
|
||||
return ItemStack.read(context.tileData.getCompound("Filter"));
|
||||
}
|
||||
|
||||
private int getFilterAmount(MovementContext context) {
|
||||
return context.tileData.getInt("FilterAmount");
|
||||
}
|
||||
|
||||
}
|
|
@ -30,7 +30,7 @@ public class TransposerBlock extends BeltAttachableLogisticalBlock implements IW
|
|||
public TransposerBlock() {
|
||||
setDefaultState(getDefaultState().with(POWERED, false));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasTileEntity(BlockState state) {
|
||||
return true;
|
||||
|
|
|
@ -109,7 +109,7 @@ public class AttributeFilterScreen extends AbstractFilterScreen<AttributeFilterC
|
|||
attributeSelector.titled(stack.getDisplayName().getFormattedText() + "...");
|
||||
attributesOfItem.clear();
|
||||
for (ItemAttribute itemAttribute : ItemAttribute.types)
|
||||
attributesOfItem.addAll(itemAttribute.listAttributesOf(stack));
|
||||
attributesOfItem.addAll(itemAttribute.listAttributesOf(stack, this.minecraft.world));
|
||||
List<String> options = attributesOfItem.stream().map(ItemAttribute::format).collect(Collectors.toList());
|
||||
attributeSelector.forOptions(options);
|
||||
attributeSelector.active = true;
|
||||
|
|
|
@ -152,11 +152,11 @@ public class FilterItem extends Item implements INamedContainerProvider {
|
|||
return newInv;
|
||||
}
|
||||
|
||||
public static boolean test(ItemStack stack, ItemStack filter) {
|
||||
return test(stack, filter, false);
|
||||
public static boolean test(World world, ItemStack stack, ItemStack filter) {
|
||||
return test(world, stack, filter, false);
|
||||
}
|
||||
|
||||
private static boolean test(ItemStack stack, ItemStack filter, boolean matchNBT) {
|
||||
private static boolean test(World world, ItemStack stack, ItemStack filter, boolean matchNBT) {
|
||||
if (filter.isEmpty())
|
||||
return true;
|
||||
|
||||
|
@ -172,7 +172,7 @@ public class FilterItem extends Item implements INamedContainerProvider {
|
|||
ItemStack stackInSlot = filterItems.getStackInSlot(slot);
|
||||
if (stackInSlot.isEmpty())
|
||||
continue;
|
||||
boolean matches = test(stack, stackInSlot, respectNBT);
|
||||
boolean matches = test(world, stack, stackInSlot, respectNBT);
|
||||
if (matches)
|
||||
return !blacklist;
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ public class FilterItem extends Item implements INamedContainerProvider {
|
|||
ListNBT attributes = filter.getOrCreateTag().getList("MatchedAttributes", NBT.TAG_COMPOUND);
|
||||
for (INBT inbt : attributes) {
|
||||
ItemAttribute attribute = ItemAttribute.fromNBT((CompoundNBT) inbt);
|
||||
boolean matches = attribute.appliesTo(stack);
|
||||
boolean matches = attribute.appliesTo(stack, world);
|
||||
|
||||
if (matches) {
|
||||
switch (whitelistMode) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -12,20 +13,27 @@ import org.apache.commons.lang3.StringUtils;
|
|||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.modules.logistics.InWorldProcessing;
|
||||
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.IRecipe;
|
||||
import net.minecraft.item.crafting.IRecipeType;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.tileentity.AbstractFurnaceTileEntity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||
|
||||
public interface ItemAttribute {
|
||||
|
||||
|
@ -41,7 +49,15 @@ public interface ItemAttribute {
|
|||
return attributeType;
|
||||
}
|
||||
|
||||
public boolean appliesTo(ItemStack stack);
|
||||
default boolean appliesTo(ItemStack stack, World world) {
|
||||
return appliesTo(stack);
|
||||
}
|
||||
|
||||
boolean appliesTo(ItemStack stack);
|
||||
|
||||
default List<ItemAttribute> listAttributesOf(ItemStack stack, World world) {
|
||||
return listAttributesOf(stack);
|
||||
}
|
||||
|
||||
public List<ItemAttribute> listAttributesOf(ItemStack stack);
|
||||
|
||||
|
@ -73,7 +89,7 @@ public interface ItemAttribute {
|
|||
default boolean canRead(CompoundNBT nbt) {
|
||||
return nbt.contains(getNBTKey());
|
||||
}
|
||||
|
||||
|
||||
default String getNBTKey() {
|
||||
return getTranslationKey();
|
||||
}
|
||||
|
@ -93,28 +109,55 @@ public interface ItemAttribute {
|
|||
BADLY_DAMAGED(s -> s.isDamaged() && s.getDamage() / s.getMaxDamage() > 3 / 4f),
|
||||
NOT_STACKABLE(Predicates.not(ItemStack::isStackable)),
|
||||
EQUIPABLE(s -> s.getEquipmentSlot() != null),
|
||||
FURNACE_FUEL(AbstractFurnaceTileEntity::isFuel);
|
||||
FURNACE_FUEL(AbstractFurnaceTileEntity::isFuel),
|
||||
WASHABLE(InWorldProcessing::isWashable),
|
||||
SMELTABLE((s, w) -> testRecipe(s, w, IRecipeType.SMELTING)),
|
||||
SMOKABLE((s, w) -> testRecipe(s, w, IRecipeType.SMOKING)),
|
||||
BLASTABLE((s, w) -> testRecipe(s, w, IRecipeType.BLASTING));
|
||||
|
||||
private static final RecipeWrapper RECIPE_WRAPPER = new RecipeWrapper(new ItemStackHandler(1));
|
||||
private Predicate<ItemStack> test;
|
||||
private BiPredicate<ItemStack, World> testWithWorld;
|
||||
|
||||
private StandardTraits(Predicate<ItemStack> test) {
|
||||
this.test = test;
|
||||
}
|
||||
|
||||
private static boolean testRecipe(ItemStack s, World w, IRecipeType<? extends IRecipe<IInventory>> smelting) {
|
||||
RECIPE_WRAPPER.setInventorySlotContents(0, s.copy());
|
||||
return w.getRecipeManager().getRecipe(smelting, RECIPE_WRAPPER, w).isPresent();
|
||||
}
|
||||
|
||||
private StandardTraits(BiPredicate<ItemStack, World> test) {
|
||||
this.testWithWorld = test;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appliesTo(ItemStack stack, World world) {
|
||||
if (testWithWorld != null)
|
||||
return testWithWorld.test(stack, world);
|
||||
return appliesTo(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appliesTo(ItemStack stack) {
|
||||
return test.test(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemAttribute> listAttributesOf(ItemStack stack) {
|
||||
public List<ItemAttribute> listAttributesOf(ItemStack stack, World world) {
|
||||
List<ItemAttribute> attributes = new ArrayList<>();
|
||||
for (StandardTraits trait : values())
|
||||
if (trait.test.test(stack))
|
||||
if (trait.appliesTo(stack, world))
|
||||
attributes.add(trait);
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemAttribute> listAttributesOf(ItemStack stack) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTranslationKey() {
|
||||
return Lang.asId(name());
|
||||
|
|
|
@ -14,7 +14,7 @@ Technology that empowers the player.'''
|
|||
[[dependencies.create]]
|
||||
modId="forge"
|
||||
mandatory=true
|
||||
versionRange="[28.1.20,)"
|
||||
versionRange="[28.1.56,)"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
|
||||
|
|
|
@ -545,6 +545,10 @@
|
|||
|
||||
"create.item_attributes.placeable": "is placeable",
|
||||
"create.item_attributes.consumable": "can be eaten",
|
||||
"create.item_attributes.smeltable": "can be Smelted",
|
||||
"create.item_attributes.washable": "can be Washed",
|
||||
"create.item_attributes.smokable": "can be Smoked",
|
||||
"create.item_attributes.blastable": "is smeltable in Blast Furnace",
|
||||
"create.item_attributes.enchanted": "is enchanted",
|
||||
"create.item_attributes.damaged": "is damaged",
|
||||
"create.item_attributes.badly_damaged": "is heavily damaged",
|
||||
|
|
Loading…
Reference in a new issue