mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-14 22:44:07 +01:00
Merge branch 'mc1.18/dev' into mc1.19/dev
This commit is contained in:
commit
34c9ae4a47
@ -1259,8 +1259,10 @@
|
||||
"create.item_attributes.smeltable.inverted": "cannot be Smelted",
|
||||
"create.item_attributes.smokable": "can be Smoked",
|
||||
"create.item_attributes.smokable.inverted": "cannot be Smoked",
|
||||
"create.item_attributes.blastable": "is smeltable in Blast Furnace",
|
||||
"create.item_attributes.blastable.inverted": "is not smeltable in Blast Furnace",
|
||||
"create.item_attributes.blastable": "can be Smelted in a Blast Furnace",
|
||||
"create.item_attributes.blastable.inverted": "cannot be Smelted in a Blast Furnace",
|
||||
"create.item_attributes.compostable": "can be composted",
|
||||
"create.item_attributes.compostable.inverted": "cannot be composted",
|
||||
"create.item_attributes.shulker_level": "is shulker %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "is shulker not %1$s",
|
||||
"create.item_attributes.shulker_level.full": "full",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "kann nicht geräuchert werden",
|
||||
"create.item_attributes.blastable": "ist im Schmelzofen schmelzbar",
|
||||
"create.item_attributes.blastable.inverted": "ist nicht im Schmelzofen schmelzbar",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "ist Shulker %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "ist Shulker nicht %1$s",
|
||||
"create.item_attributes.shulker_level.full": "voll",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "no puede ser Ahumado",
|
||||
"create.item_attributes.blastable": "puede ser cocinado en un Alto Horno",
|
||||
"create.item_attributes.blastable.inverted": "no puede ser cocinado en un Alto Horno",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "es un shulker %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "no es un shulker %1$s",
|
||||
"create.item_attributes.shulker_level.full": "lleno",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "no puede ser ahumado",
|
||||
"create.item_attributes.blastable": "es fundible en el alto horno",
|
||||
"create.item_attributes.blastable.inverted": "no es fundible en el alto horno",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "es shulker %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "no es shulker %1$s",
|
||||
"create.item_attributes.shulker_level.full": "lleno",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "ne peut pas être fumé",
|
||||
"create.item_attributes.blastable": "est fondable dans un Haut fourneau",
|
||||
"create.item_attributes.blastable.inverted": "n'est pas fondable dans un Haut fourneau",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "UNLOCALIZED: is shulker %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "UNLOCALIZED: is shulker not %1$s",
|
||||
"create.item_attributes.shulker_level.full": "UNLOCALIZED: full",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "non può essere affumicato",
|
||||
"create.item_attributes.blastable": "è fondibile in un forno fusorio",
|
||||
"create.item_attributes.blastable.inverted": "non è fondibile in un forno fusorio",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "è uno shulker %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "non è uno shulker %1$s",
|
||||
"create.item_attributes.shulker_level.full": "pieno",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "燻製器で調理できないか",
|
||||
"create.item_attributes.blastable": "溶鉱炉で精錬できるかか",
|
||||
"create.item_attributes.blastable.inverted": "溶鉱炉で精錬できないか",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "%1$sシュルカーか",
|
||||
"create.item_attributes.shulker_level.inverted": "%1$sシュルカーでないか",
|
||||
"create.item_attributes.shulker_level.full": "満杯の",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "훈연될 수 없음",
|
||||
"create.item_attributes.blastable": "용광로에 녹일 수 있음",
|
||||
"create.item_attributes.blastable.inverted": "용광로에 녹일 수 없음",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "셜커가 %1$s있음",
|
||||
"create.item_attributes.shulker_level.inverted": "셜커가 %1$s있지 않음",
|
||||
"create.item_attributes.shulker_level.full": "가득 차",
|
||||
|
@ -1260,8 +1260,10 @@
|
||||
"create.item_attributes.smeltable.inverted": "UNLOCALIZED: cannot be Smelted",
|
||||
"create.item_attributes.smokable": "UNLOCALIZED: can be Smoked",
|
||||
"create.item_attributes.smokable.inverted": "UNLOCALIZED: cannot be Smoked",
|
||||
"create.item_attributes.blastable": "UNLOCALIZED: is smeltable in Blast Furnace",
|
||||
"create.item_attributes.blastable.inverted": "UNLOCALIZED: is not smeltable in Blast Furnace",
|
||||
"create.item_attributes.blastable": "UNLOCALIZED: can be Smelted in a Blast Furnace",
|
||||
"create.item_attributes.blastable.inverted": "UNLOCALIZED: cannot be Smelted in a Blast Furnace",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "UNLOCALIZED: is shulker %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "UNLOCALIZED: is shulker not %1$s",
|
||||
"create.item_attributes.shulker_level.full": "UNLOCALIZED: full",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "nie może być wędzony",
|
||||
"create.item_attributes.blastable": "może być stopiony w piecu hutniczym",
|
||||
"create.item_attributes.blastable.inverted": "nie może być stopiony w piecu hutniczym",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "jest %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "nie jest %1$s",
|
||||
"create.item_attributes.shulker_level.full": "pełna",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "Não pode ser defumado",
|
||||
"create.item_attributes.blastable": "È fundível no alto-forno",
|
||||
"create.item_attributes.blastable.inverted": "Não é fundível no alto-forno",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "O shulker é %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "O shulker não é %1$s",
|
||||
"create.item_attributes.shulker_level.full": "Cheio",
|
||||
|
@ -1260,8 +1260,10 @@
|
||||
"create.item_attributes.smeltable.inverted": "UNLOCALIZED: cannot be Smelted",
|
||||
"create.item_attributes.smokable": "UNLOCALIZED: can be Smoked",
|
||||
"create.item_attributes.smokable.inverted": "UNLOCALIZED: cannot be Smoked",
|
||||
"create.item_attributes.blastable": "UNLOCALIZED: is smeltable in Blast Furnace",
|
||||
"create.item_attributes.blastable.inverted": "UNLOCALIZED: is not smeltable in Blast Furnace",
|
||||
"create.item_attributes.blastable": "UNLOCALIZED: can be Smelted in a Blast Furnace",
|
||||
"create.item_attributes.blastable.inverted": "UNLOCALIZED: cannot be Smelted in a Blast Furnace",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "UNLOCALIZED: is shulker %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "UNLOCALIZED: is shulker not %1$s",
|
||||
"create.item_attributes.shulker_level.full": "UNLOCALIZED: full",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "nu poate fi Afumat",
|
||||
"create.item_attributes.blastable": "poate fi topit în Furnal",
|
||||
"create.item_attributes.blastable.inverted": "nu poate fi topit în Furnal",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "este shulkerul %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "nu este shulkerul %1$s",
|
||||
"create.item_attributes.shulker_level.full": "plin",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "нельзя прокоптить",
|
||||
"create.item_attributes.blastable": "плавится в доменной печи",
|
||||
"create.item_attributes.blastable.inverted": "не плавится в доменной печи",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "шалкер %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "шалкер не %1$s",
|
||||
"create.item_attributes.shulker_level.full": "полный",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "не можна Коптити",
|
||||
"create.item_attributes.blastable": "плавиться в Плавильній печі",
|
||||
"create.item_attributes.blastable.inverted": "не плавиться в Плавильній печі",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "шалкер %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "шалкер не %1$s",
|
||||
"create.item_attributes.shulker_level.full": "повний",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "不可被烟熏",
|
||||
"create.item_attributes.blastable": "可被高炉冶炼",
|
||||
"create.item_attributes.blastable.inverted": "不可被高炉冶炼",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "潜影盒是%1$s的",
|
||||
"create.item_attributes.shulker_level.inverted": "潜影盒不是%1$s的",
|
||||
"create.item_attributes.shulker_level.full": "满",
|
||||
|
@ -1262,6 +1262,8 @@
|
||||
"create.item_attributes.smokable.inverted": "不可被煙熏",
|
||||
"create.item_attributes.blastable": "可被高爐融煉",
|
||||
"create.item_attributes.blastable.inverted": "不可被高爐融煉",
|
||||
"create.item_attributes.compostable": "UNLOCALIZED: can be composted",
|
||||
"create.item_attributes.compostable.inverted": "UNLOCALIZED: cannot be composted",
|
||||
"create.item_attributes.shulker_level": "界伏盒是 %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "界伏盒不是 %1$s",
|
||||
"create.item_attributes.shulker_level.full": "滿的",
|
||||
|
@ -3,23 +3,19 @@ package com.simibubi.create.content.contraptions.components.actors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
import net.minecraft.world.level.block.AirBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||
@ -40,7 +36,7 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||
if (destroyProgress == -1)
|
||||
destroyNextTick();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void lazyTick() {
|
||||
super.lazyTick();
|
||||
@ -93,9 +89,9 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||
return;
|
||||
if (getSpeed() == 0)
|
||||
return;
|
||||
|
||||
|
||||
breakingPos = getBreakingPos();
|
||||
|
||||
|
||||
if (ticksUntilNextProgress < 0)
|
||||
return;
|
||||
if (ticksUntilNextProgress-- > 0)
|
||||
@ -114,7 +110,8 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||
|
||||
float breakSpeed = getBreakSpeed();
|
||||
destroyProgress += Mth.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress);
|
||||
level.playSound(null, worldPosition, stateToBreak.getSoundType().getHitSound(), SoundSource.NEUTRAL, .25f, 1);
|
||||
level.playSound(null, worldPosition, stateToBreak.getSoundType()
|
||||
.getHitSound(), SoundSource.NEUTRAL, .25f, 1);
|
||||
|
||||
if (destroyProgress >= 10) {
|
||||
onBlockBroken(stateToBreak);
|
||||
@ -133,28 +130,26 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||
}
|
||||
|
||||
public static boolean isBreakable(BlockState stateToBreak, float blockHardness) {
|
||||
return !(stateToBreak.getMaterial().isLiquid() || stateToBreak.getBlock() instanceof AirBlock
|
||||
|| blockHardness == -1);
|
||||
return !(stateToBreak.getMaterial()
|
||||
.isLiquid() || stateToBreak.getBlock() instanceof AirBlock || blockHardness == -1);
|
||||
}
|
||||
|
||||
public void onBlockBroken(BlockState stateToBreak) {
|
||||
FluidState FluidState = level.getFluidState(breakingPos);
|
||||
level.levelEvent(2001, breakingPos, Block.getId(stateToBreak));
|
||||
BlockEntity tileentity = stateToBreak.hasBlockEntity() ? level.getBlockEntity(breakingPos) : null;
|
||||
Vec3 vec = VecHelper.offsetRandomly(VecHelper.getCenterOf(breakingPos), level.random, .125f);
|
||||
|
||||
Block.getDrops(stateToBreak, (ServerLevel) level, breakingPos, tileentity).forEach((stack) -> {
|
||||
if (!stack.isEmpty() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)
|
||||
&& !level.restoringBlockSnapshots) {
|
||||
ItemEntity itementity = new ItemEntity(level, vec.x, vec.y, vec.z, stack);
|
||||
itementity.setDefaultPickUpDelay();
|
||||
itementity.setDeltaMovement(Vec3.ZERO);
|
||||
level.addFreshEntity(itementity);
|
||||
}
|
||||
BlockHelper.destroyBlock(level, breakingPos, 1f, (stack) -> {
|
||||
if (stack.isEmpty())
|
||||
return;
|
||||
if (!level.getGameRules()
|
||||
.getBoolean(GameRules.RULE_DOBLOCKDROPS))
|
||||
return;
|
||||
if (level.restoringBlockSnapshots)
|
||||
return;
|
||||
|
||||
ItemEntity itementity = new ItemEntity(level, vec.x, vec.y, vec.z, stack);
|
||||
itementity.setDefaultPickUpDelay();
|
||||
itementity.setDeltaMovement(Vec3.ZERO);
|
||||
level.addFreshEntity(itementity);
|
||||
});
|
||||
if (level instanceof ServerLevel)
|
||||
stateToBreak.spawnAfterBreak((ServerLevel) level, breakingPos, ItemStack.EMPTY, true);
|
||||
level.setBlock(breakingPos, FluidState.createLegacyBlock(), 3);
|
||||
}
|
||||
|
||||
protected float getBreakSpeed() {
|
||||
|
@ -104,7 +104,8 @@ public class HarvesterMovementBehaviour implements MovementBehaviour {
|
||||
dropItem(context, stack);
|
||||
});
|
||||
|
||||
world.setBlockAndUpdate(pos, cutCrop(world, pos, stateVisited));
|
||||
BlockState cutCrop = cutCrop(world, pos, stateVisited);
|
||||
world.setBlockAndUpdate(pos, cutCrop.canSurvive(world, pos) ? cutCrop : Blocks.AIR.defaultBlockState());
|
||||
}
|
||||
|
||||
public boolean isValidCrop(Level world, BlockPos pos, BlockState state) {
|
||||
|
@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.actors;
|
||||
|
||||
import com.simibubi.create.content.contraptions.components.actors.PloughBlock.PloughFakePlayer;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.content.logistics.trains.ITrackBlock;
|
||||
import com.simibubi.create.content.logistics.trains.track.FakeTrackBlock;
|
||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
@ -105,6 +106,8 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour {
|
||||
return false;
|
||||
if (state.getBlock() instanceof NetherPortalBlock)
|
||||
return false;
|
||||
if (state.getBlock() instanceof ITrackBlock)
|
||||
return true;
|
||||
if (state.getBlock() instanceof FakeTrackBlock)
|
||||
return false;
|
||||
return state.getCollisionShape(world, breakingPos)
|
||||
|
@ -304,13 +304,13 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||
localVec = localVec.subtract(rotationOffset);
|
||||
localVec = applyRotation(localVec, partialTicks);
|
||||
localVec = localVec.add(rotationOffset)
|
||||
.add(getAnchorVec());
|
||||
.add(getPrevAnchorVec());
|
||||
return localVec;
|
||||
}
|
||||
|
||||
public Vec3 toLocalVector(Vec3 globalVec, float partialTicks) {
|
||||
Vec3 rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
|
||||
globalVec = globalVec.subtract(getAnchorVec())
|
||||
globalVec = globalVec.subtract(getPrevAnchorVec())
|
||||
.subtract(rotationOffset);
|
||||
globalVec = reverseRotation(globalVec, partialTicks);
|
||||
globalVec = globalVec.add(rotationOffset);
|
||||
@ -519,6 +519,10 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||
public Vec3 getAnchorVec() {
|
||||
return position();
|
||||
}
|
||||
|
||||
public Vec3 getPrevAnchorVec() {
|
||||
return getPrevPositionVec();
|
||||
}
|
||||
|
||||
public float getYawOffset() {
|
||||
return 0;
|
||||
@ -792,9 +796,11 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||
public Vec3 getContactPointMotion(Vec3 globalContactPoint) {
|
||||
if (prevPosInvalid)
|
||||
return Vec3.ZERO;
|
||||
|
||||
Vec3 contactPoint = toGlobalVector(toLocalVector(globalContactPoint, 0), 1);
|
||||
return contactPoint.subtract(globalContactPoint)
|
||||
.add(position().subtract(getPrevPositionVec()));
|
||||
Vec3 contraptionLocalMovement = contactPoint.subtract(globalContactPoint);
|
||||
Vec3 contraptionAnchorMovement = position().subtract(getPrevPositionVec());
|
||||
return contraptionLocalMovement.add(contraptionAnchorMovement);
|
||||
}
|
||||
|
||||
public boolean canCollideWith(Entity e) {
|
||||
@ -831,7 +837,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public abstract void doLocalTransforms(float partialTicks, PoseStack[] matrixStacks);
|
||||
public abstract void applyLocalTransforms(PoseStack matrixStack, float partialTicks);
|
||||
|
||||
public static class ContraptionRotationState {
|
||||
public static final ContraptionRotationState NONE = new ContraptionRotationState();
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||
|
||||
import java.util.List;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ -86,10 +87,19 @@ public class ContraptionHandlerClient {
|
||||
Vec3 origin = rayInputs.getFirst();
|
||||
Vec3 target = rayInputs.getSecond();
|
||||
AABB aabb = new AABB(origin, target).inflate(16);
|
||||
List<AbstractContraptionEntity> intersectingContraptions =
|
||||
mc.level.getEntitiesOfClass(AbstractContraptionEntity.class, aabb);
|
||||
|
||||
for (AbstractContraptionEntity contraptionEntity : intersectingContraptions) {
|
||||
Collection<WeakReference<AbstractContraptionEntity>> contraptions =
|
||||
ContraptionHandler.loadedContraptions.get(mc.level)
|
||||
.values();
|
||||
|
||||
for (WeakReference<AbstractContraptionEntity> ref : contraptions) {
|
||||
AbstractContraptionEntity contraptionEntity = ref.get();
|
||||
if (contraptionEntity == null)
|
||||
continue;
|
||||
if (!contraptionEntity.getBoundingBox()
|
||||
.intersects(aabb))
|
||||
continue;
|
||||
|
||||
BlockHitResult rayTraceResult = rayTraceContraption(origin, target, contraptionEntity);
|
||||
if (rayTraceResult == null)
|
||||
continue;
|
||||
|
@ -226,15 +226,14 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity {
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void doLocalTransforms(float partialTicks, PoseStack[] matrixStacks) {
|
||||
public void applyLocalTransforms(PoseStack matrixStack, float partialTicks) {
|
||||
float angle = getAngle(partialTicks);
|
||||
Axis axis = getRotationAxis();
|
||||
|
||||
for (PoseStack stack : matrixStacks)
|
||||
TransformStack.cast(stack)
|
||||
.nudge(getId())
|
||||
.centre()
|
||||
.rotate(angle, axis)
|
||||
.unCentre();
|
||||
TransformStack.cast(matrixStack)
|
||||
.nudge(getId())
|
||||
.centre()
|
||||
.rotate(angle, axis)
|
||||
.unCentre();
|
||||
}
|
||||
}
|
||||
|
@ -493,7 +493,14 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
|
||||
|
||||
@Override
|
||||
public Vec3 getAnchorVec() {
|
||||
return new Vec3(getX() - .5, getY(), getZ() - .5);
|
||||
Vec3 anchorVec = super.getAnchorVec();
|
||||
return anchorVec.subtract(.5, 0, .5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3 getPrevAnchorVec() {
|
||||
Vec3 prevAnchorVec = super.getPrevAnchorVec();
|
||||
return prevAnchorVec.subtract(.5, 0, .5);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -514,52 +521,48 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void doLocalTransforms(float partialTicks, PoseStack[] matrixStacks) {
|
||||
public void applyLocalTransforms(PoseStack matrixStack, float partialTicks) {
|
||||
float angleInitialYaw = getInitialYaw();
|
||||
float angleYaw = getViewYRot(partialTicks);
|
||||
float anglePitch = getViewXRot(partialTicks);
|
||||
|
||||
for (PoseStack stack : matrixStacks)
|
||||
stack.translate(-.5f, 0, -.5f);
|
||||
matrixStack.translate(-.5f, 0, -.5f);
|
||||
|
||||
Entity ridingEntity = getVehicle();
|
||||
if (ridingEntity instanceof AbstractMinecart)
|
||||
repositionOnCart(partialTicks, matrixStacks, ridingEntity);
|
||||
repositionOnCart(matrixStack, partialTicks, ridingEntity);
|
||||
else if (ridingEntity instanceof AbstractContraptionEntity) {
|
||||
if (ridingEntity.getVehicle() instanceof AbstractMinecart)
|
||||
repositionOnCart(partialTicks, matrixStacks, ridingEntity.getVehicle());
|
||||
repositionOnCart(matrixStack, partialTicks, ridingEntity.getVehicle());
|
||||
else
|
||||
repositionOnContraption(partialTicks, matrixStacks, ridingEntity);
|
||||
repositionOnContraption(matrixStack, partialTicks, ridingEntity);
|
||||
}
|
||||
|
||||
for (PoseStack stack : matrixStacks)
|
||||
TransformStack.cast(stack)
|
||||
.nudge(getId())
|
||||
.centre()
|
||||
.rotateY(angleYaw)
|
||||
.rotateZ(anglePitch)
|
||||
.rotateY(angleInitialYaw)
|
||||
.unCentre();
|
||||
TransformStack.cast(matrixStack)
|
||||
.nudge(getId())
|
||||
.centre()
|
||||
.rotateY(angleYaw)
|
||||
.rotateZ(anglePitch)
|
||||
.rotateY(angleInitialYaw)
|
||||
.unCentre();
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private void repositionOnContraption(float partialTicks, PoseStack[] matrixStacks, Entity ridingEntity) {
|
||||
private void repositionOnContraption(PoseStack matrixStack, float partialTicks, Entity ridingEntity) {
|
||||
Vec3 pos = getContraptionOffset(partialTicks, ridingEntity);
|
||||
for (PoseStack stack : matrixStacks)
|
||||
stack.translate(pos.x, pos.y, pos.z);
|
||||
matrixStack.translate(pos.x, pos.y, pos.z);
|
||||
}
|
||||
|
||||
// Minecarts do not always render at their exact location, so the contraption
|
||||
// has to adjust aswell
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private void repositionOnCart(float partialTicks, PoseStack[] matrixStacks, Entity ridingEntity) {
|
||||
private void repositionOnCart(PoseStack matrixStack, float partialTicks, Entity ridingEntity) {
|
||||
Vec3 cartPos = getCartOffset(partialTicks, ridingEntity);
|
||||
|
||||
if (cartPos == Vec3.ZERO)
|
||||
return;
|
||||
|
||||
for (PoseStack stack : matrixStacks)
|
||||
stack.translate(cartPos.x, cartPos.y, cartPos.z);
|
||||
matrixStack.translate(cartPos.x, cartPos.y, cartPos.z);
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
|
@ -176,7 +176,7 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doLocalTransforms(float partialTicks, PoseStack[] matrixStacks) { }
|
||||
public void applyLocalTransforms(PoseStack matrixStack, float partialTicks) { }
|
||||
|
||||
public void updateClientMotion() {
|
||||
float modifier = movementAxis.getAxisDirection()
|
||||
|
@ -34,7 +34,7 @@ public class ContraptionMatrices {
|
||||
this.viewProjection.pushPose();
|
||||
transform(this.viewProjection, viewProjection);
|
||||
model.pushPose();
|
||||
entity.doLocalTransforms(partialTicks, new PoseStack[] { model });
|
||||
entity.applyLocalTransforms(model, partialTicks);
|
||||
|
||||
modelViewProjection.pushPose();
|
||||
transform(modelViewProjection, viewProjection);
|
||||
|
@ -11,6 +11,7 @@ import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
import net.minecraftforge.network.NetworkEvent.Context;
|
||||
|
||||
@ -54,7 +55,9 @@ public class ContraptionInteractionPacket extends SimplePacketBase {
|
||||
if (!(entityByID instanceof AbstractContraptionEntity))
|
||||
return;
|
||||
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
|
||||
double d = sender.getAttribute(ForgeMod.REACH_DISTANCE.get()).getValue() + 10;
|
||||
AABB bb = contraptionEntity.getBoundingBox();
|
||||
double boundsExtra = Math.max(bb.getXsize(), bb.getYsize());
|
||||
double d = sender.getAttribute(ForgeMod.REACH_DISTANCE.get()).getValue() + 10 + boundsExtra;
|
||||
if (!sender.hasLineOfSight(entityByID))
|
||||
d -= 3;
|
||||
d *= d;
|
||||
|
@ -8,6 +8,7 @@ import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllTags.AllBlockTags;
|
||||
import com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow;
|
||||
import com.simibubi.create.content.contraptions.fluids.pipes.AxisPipeBlock;
|
||||
import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock;
|
||||
@ -173,7 +174,8 @@ public class FluidPropagator {
|
||||
return false;
|
||||
if (VanillaFluidTargets.shouldPipesConnectTo(connectedState))
|
||||
return true;
|
||||
if (BlockHelper.hasBlockSolidSide(connectedState, reader, connectedPos, side.getOpposite()))
|
||||
if (BlockHelper.hasBlockSolidSide(connectedState, reader, connectedPos, side.getOpposite())
|
||||
&& !AllBlockTags.FAN_TRANSPARENT.matches(connectedState))
|
||||
return false;
|
||||
if (hasFluidCapability(reader, connectedPos, side.getOpposite()))
|
||||
return false;
|
||||
|
@ -33,52 +33,67 @@ public class BlazeBurnerRenderer extends SafeTileEntityRenderer<BlazeBurnerTileE
|
||||
public BlazeBurnerRenderer(BlockEntityRendererProvider.Context context) {}
|
||||
|
||||
@Override
|
||||
protected void renderSafe(BlazeBurnerTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer,
|
||||
protected void renderSafe(BlazeBurnerTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource bufferSource,
|
||||
int light, int overlay) {
|
||||
HeatLevel heatLevel = te.getHeatLevelFromBlock();
|
||||
if (heatLevel == HeatLevel.NONE)
|
||||
return;
|
||||
|
||||
float horizontalAngle = AngleHelper.rad(te.headAngle.getValue(partialTicks));
|
||||
Level level = te.getLevel();
|
||||
int hashCode = te.hashCode();
|
||||
float animation = te.headAnimation.getValue(partialTicks) * .175f;
|
||||
BlockState blockState = te.getBlockState();
|
||||
float animation = te.headAnimation.getValue(partialTicks) * .175f;
|
||||
float horizontalAngle = AngleHelper.rad(te.headAngle.getValue(partialTicks));
|
||||
boolean canDrawFlame = heatLevel.isAtLeast(HeatLevel.FADING);
|
||||
boolean drawGoggles = te.goggles;
|
||||
boolean drawHat = te.hat;
|
||||
int hashCode = te.hashCode();
|
||||
|
||||
renderShared(level, buffer, null, ms, blockState, horizontalAngle, animation, drawGoggles, drawHat, hashCode);
|
||||
renderShared(ms, null, bufferSource,
|
||||
level, blockState, heatLevel, animation, horizontalAngle,
|
||||
canDrawFlame, drawGoggles, drawHat, hashCode);
|
||||
}
|
||||
|
||||
public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
|
||||
ContraptionMatrices matrices, MultiBufferSource buffer, LerpedFloat headAngle, boolean conductor) {
|
||||
ContraptionMatrices matrices, MultiBufferSource bufferSource, LerpedFloat headAngle, boolean conductor) {
|
||||
BlockState state = context.state;
|
||||
if (BlazeBurnerBlock.getHeatLevelOf(state) == HeatLevel.KINDLED)
|
||||
state = state.setValue(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.FADING);
|
||||
float value = AngleHelper.rad(headAngle.getValue(AnimationTickHolder.getPartialTicks(context.world)));
|
||||
renderShared(context.world, buffer, matrices.getModel(), matrices.getViewProjection(), state, value, 0,
|
||||
context.tileData.contains("Goggles"), conductor, context.hashCode());
|
||||
HeatLevel heatLevel = BlazeBurnerBlock.getHeatLevelOf(state);
|
||||
if (heatLevel == HeatLevel.NONE)
|
||||
return;
|
||||
|
||||
if (!heatLevel.isAtLeast(HeatLevel.FADING)) {
|
||||
heatLevel = HeatLevel.FADING;
|
||||
}
|
||||
|
||||
Level level = context.world;
|
||||
float horizontalAngle = AngleHelper.rad(headAngle.getValue(AnimationTickHolder.getPartialTicks(level)));
|
||||
boolean drawGoggles = context.tileData.contains("Goggles");
|
||||
boolean drawHat = conductor || context.tileData.contains("TrainHat");
|
||||
int hashCode = context.hashCode();
|
||||
|
||||
renderShared(matrices.getViewProjection(), matrices.getModel(), bufferSource,
|
||||
level, state, heatLevel, 0, horizontalAngle,
|
||||
false, drawGoggles, drawHat, hashCode);
|
||||
}
|
||||
|
||||
private static void renderShared(Level level, MultiBufferSource buffer, @Nullable PoseStack modelTransform,
|
||||
PoseStack ms, BlockState blockState, float horizontalAngle, float animation, boolean drawGoggles,
|
||||
boolean drawHat, int hashCode) {
|
||||
private static void renderShared(PoseStack ms, @Nullable PoseStack modelTransform, MultiBufferSource bufferSource,
|
||||
Level level, BlockState blockState, HeatLevel heatLevel, float animation, float horizontalAngle,
|
||||
boolean canDrawFlame, boolean drawGoggles, boolean drawHat, int hashCode) {
|
||||
|
||||
boolean blockAbove = animation > 0.125f;
|
||||
HeatLevel heatLevel = BlazeBurnerBlock.getHeatLevelOf(blockState);
|
||||
float time = AnimationTickHolder.getRenderTime(level);
|
||||
float renderTick = time + (hashCode % 13) * 16f;
|
||||
float offsetMult = heatLevel.isAtLeast(HeatLevel.FADING) ? 64 : 16;
|
||||
float offset = Mth.sin((float) ((renderTick / 16f) % (2 * Math.PI))) / offsetMult;
|
||||
float offset1 = Mth.sin((float) ((renderTick / 16f + Math.PI) % (2 * Math.PI))) / offsetMult;
|
||||
float offset2 = Mth.sin((float) ((renderTick / 16f + Math.PI / 2) % (2 * Math.PI))) / offsetMult;
|
||||
float headY = offset - (animation * .75f);
|
||||
|
||||
VertexConsumer solid = buffer.getBuffer(RenderType.solid());
|
||||
VertexConsumer cutout = buffer.getBuffer(RenderType.cutoutMipped());
|
||||
VertexConsumer solid = bufferSource.getBuffer(RenderType.solid());
|
||||
VertexConsumer cutout = bufferSource.getBuffer(RenderType.cutoutMipped());
|
||||
|
||||
ms.pushPose();
|
||||
|
||||
if (modelTransform == null && heatLevel.isAtLeast(HeatLevel.FADING) && blockAbove) {
|
||||
if (canDrawFlame && blockAbove) {
|
||||
SpriteShiftEntry spriteShift =
|
||||
heatLevel == HeatLevel.SEETHING ? AllSpriteShifts.SUPER_BURNER_FLAME : AllSpriteShifts.BURNER_FLAME;
|
||||
|
||||
@ -102,68 +117,87 @@ public class BlazeBurnerRenderer extends SafeTileEntityRenderer<BlazeBurnerTileE
|
||||
uScroll = uScroll - Math.floor(uScroll);
|
||||
uScroll = uScroll * spriteWidth / 2;
|
||||
|
||||
draw(CachedBufferer.partial(AllBlockPartials.BLAZE_BURNER_FLAME, blockState)
|
||||
.shiftUVScrolling(spriteShift, (float) uScroll, (float) vScroll), horizontalAngle, modelTransform, ms,
|
||||
cutout);
|
||||
SuperByteBuffer flameBuffer = CachedBufferer.partial(AllBlockPartials.BLAZE_BURNER_FLAME, blockState);
|
||||
if (modelTransform != null)
|
||||
flameBuffer.transform(modelTransform);
|
||||
flameBuffer.shiftUVScrolling(spriteShift, (float) uScroll, (float) vScroll);
|
||||
draw(flameBuffer, horizontalAngle, ms, cutout);
|
||||
}
|
||||
|
||||
PartialModel blazeModel = modelTransform != null ? AllBlockPartials.BLAZE_IDLE : AllBlockPartials.BLAZE_INERT;
|
||||
if (heatLevel.isAtLeast(HeatLevel.SEETHING))
|
||||
PartialModel blazeModel;
|
||||
if (heatLevel.isAtLeast(HeatLevel.SEETHING)) {
|
||||
blazeModel = blockAbove ? AllBlockPartials.BLAZE_SUPER_ACTIVE : AllBlockPartials.BLAZE_SUPER;
|
||||
else if (heatLevel.isAtLeast(HeatLevel.FADING))
|
||||
} else if (heatLevel.isAtLeast(HeatLevel.FADING)) {
|
||||
blazeModel = blockAbove && heatLevel.isAtLeast(HeatLevel.KINDLED) ? AllBlockPartials.BLAZE_ACTIVE
|
||||
: AllBlockPartials.BLAZE_IDLE;
|
||||
} else {
|
||||
blazeModel = AllBlockPartials.BLAZE_INERT;
|
||||
}
|
||||
|
||||
float headY = offset - (animation * .75f);
|
||||
SuperByteBuffer blazeBuffer = CachedBufferer.partial(blazeModel, blockState);
|
||||
if (modelTransform != null)
|
||||
blazeBuffer.transform(modelTransform);
|
||||
blazeBuffer.translate(0, headY, 0);
|
||||
draw(blazeBuffer, horizontalAngle, ms, solid);
|
||||
|
||||
draw(CachedBufferer.partial(blazeModel, blockState)
|
||||
.translate(0, headY, 0), horizontalAngle, modelTransform, ms, solid);
|
||||
if (drawGoggles) {
|
||||
PartialModel gogglesModel = blazeModel == AllBlockPartials.BLAZE_INERT
|
||||
? AllBlockPartials.BLAZE_GOGGLES_SMALL : AllBlockPartials.BLAZE_GOGGLES;
|
||||
|
||||
if (drawGoggles)
|
||||
draw(CachedBufferer.partial(blazeModel == AllBlockPartials.BLAZE_INERT
|
||||
? AllBlockPartials.BLAZE_GOGGLES_SMALL : AllBlockPartials.BLAZE_GOGGLES, blockState)
|
||||
.translate(0, headY + 8 / 16f, 0), horizontalAngle, modelTransform, ms, solid);
|
||||
SuperByteBuffer gogglesBuffer = CachedBufferer.partial(gogglesModel, blockState);
|
||||
if (modelTransform != null)
|
||||
gogglesBuffer.transform(modelTransform);
|
||||
gogglesBuffer.translate(0, headY + 8 / 16f, 0);
|
||||
draw(gogglesBuffer, horizontalAngle, ms, solid);
|
||||
}
|
||||
|
||||
if (drawHat) {
|
||||
SuperByteBuffer partial = CachedBufferer.partial(AllBlockPartials.TRAIN_HAT, blockState)
|
||||
.translate(0, headY, 0);
|
||||
SuperByteBuffer hatBuffer = CachedBufferer.partial(AllBlockPartials.TRAIN_HAT, blockState);
|
||||
if (modelTransform != null)
|
||||
hatBuffer.transform(modelTransform);
|
||||
hatBuffer.translate(0, headY, 0);
|
||||
if (blazeModel == AllBlockPartials.BLAZE_INERT) {
|
||||
partial.translateY(0.5f)
|
||||
hatBuffer.translateY(0.5f)
|
||||
.centre()
|
||||
.scale(0.75f)
|
||||
.unCentre();
|
||||
} else {
|
||||
partial.translateY(0.75f);
|
||||
hatBuffer.translateY(0.75f);
|
||||
}
|
||||
if (modelTransform != null)
|
||||
partial.transform(modelTransform);
|
||||
partial
|
||||
hatBuffer
|
||||
.rotateCentered(Direction.UP, horizontalAngle + Mth.PI)
|
||||
.translate(0.5f, 0, 0.5f)
|
||||
.light(LightTexture.FULL_BRIGHT)
|
||||
.renderInto(ms, solid);
|
||||
}
|
||||
|
||||
if (heatLevel.isAtLeast(HeatLevel.FADING) || modelTransform != null) {
|
||||
PartialModel rods = heatLevel == HeatLevel.SEETHING ? AllBlockPartials.BLAZE_BURNER_SUPER_RODS
|
||||
if (heatLevel.isAtLeast(HeatLevel.FADING)) {
|
||||
PartialModel rodsModel = heatLevel == HeatLevel.SEETHING ? AllBlockPartials.BLAZE_BURNER_SUPER_RODS
|
||||
: AllBlockPartials.BLAZE_BURNER_RODS;
|
||||
PartialModel rods2 = heatLevel == HeatLevel.SEETHING ? AllBlockPartials.BLAZE_BURNER_SUPER_RODS_2
|
||||
PartialModel rodsModel2 = heatLevel == HeatLevel.SEETHING ? AllBlockPartials.BLAZE_BURNER_SUPER_RODS_2
|
||||
: AllBlockPartials.BLAZE_BURNER_RODS_2;
|
||||
draw(CachedBufferer.partial(rods, blockState)
|
||||
.translate(0, offset1 + animation + .125f, 0), 0, modelTransform, ms, solid);
|
||||
draw(CachedBufferer.partial(rods2, blockState)
|
||||
.translate(0, offset2 + animation - 3 / 16f, 0), 0, modelTransform, ms, solid);
|
||||
|
||||
SuperByteBuffer rodsBuffer = CachedBufferer.partial(rodsModel, blockState);
|
||||
if (modelTransform != null)
|
||||
rodsBuffer.transform(modelTransform);
|
||||
rodsBuffer.translate(0, offset1 + animation + .125f, 0)
|
||||
.light(LightTexture.FULL_BRIGHT)
|
||||
.renderInto(ms, solid);
|
||||
|
||||
SuperByteBuffer rodsBuffer2 = CachedBufferer.partial(rodsModel2, blockState);
|
||||
if (modelTransform != null)
|
||||
rodsBuffer2.transform(modelTransform);
|
||||
rodsBuffer2.translate(0, offset2 + animation - 3 / 16f, 0)
|
||||
.light(LightTexture.FULL_BRIGHT)
|
||||
.renderInto(ms, solid);
|
||||
}
|
||||
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
private static void draw(SuperByteBuffer blazeBuffer, float horizontalAngle, @Nullable PoseStack modelTransform,
|
||||
PoseStack ms, VertexConsumer vb) {
|
||||
if (modelTransform != null)
|
||||
blazeBuffer.transform(modelTransform);
|
||||
blazeBuffer.rotateCentered(Direction.UP, horizontalAngle)
|
||||
private static void draw(SuperByteBuffer buffer, float horizontalAngle, PoseStack ms, VertexConsumer vc) {
|
||||
buffer.rotateCentered(Direction.UP, horizontalAngle)
|
||||
.light(LightTexture.FULL_BRIGHT)
|
||||
.renderInto(ms, vb);
|
||||
.renderInto(ms, vc);
|
||||
}
|
||||
}
|
||||
|
@ -40,9 +40,10 @@ public class ScoreboardDisplaySource extends ValueListDisplaySource {
|
||||
return sLevel.getScoreboard()
|
||||
.getPlayerScores(objective)
|
||||
.stream()
|
||||
.limit(maxRows)
|
||||
.map(score -> IntAttached.with(score.getScore(), Components.literal(score.getOwner()).copy()))
|
||||
.sorted(IntAttached.comparator());
|
||||
.map(score -> IntAttached.with(score.getScore(), Components.literal(score.getOwner())
|
||||
.copy()))
|
||||
.sorted(IntAttached.comparator())
|
||||
.limit(maxRows);
|
||||
}
|
||||
|
||||
private ImmutableList<IntAttached<MutableComponent>> notFound(String objective) {
|
||||
|
@ -55,9 +55,8 @@ import net.minecraft.world.level.block.entity.JukeboxBlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraftforge.items.wrapper.SidedInvWrapper;
|
||||
|
||||
public class AllArmInteractionPointTypes {
|
||||
@ -605,16 +604,29 @@ public class AllArmInteractionPointTypes {
|
||||
@Nullable
|
||||
@Override
|
||||
protected IItemHandler getHandler() {
|
||||
if (!cachedHandler.isPresent()) {
|
||||
cachedHandler = LazyOptional.of(() -> {
|
||||
ComposterBlock composterBlock = (ComposterBlock) Blocks.COMPOSTER;
|
||||
WorldlyContainer container = composterBlock.getContainer(cachedState, level, pos);
|
||||
SidedInvWrapper insertionHandler = new SidedInvWrapper(container, Direction.UP);
|
||||
SidedInvWrapper extractionHandler = new SidedInvWrapper(container, Direction.DOWN);
|
||||
return new CombinedInvWrapper(insertionHandler, extractionHandler);
|
||||
});
|
||||
}
|
||||
return cachedHandler.orElse(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
protected WorldlyContainer getContainer() {
|
||||
ComposterBlock composterBlock = (ComposterBlock) Blocks.COMPOSTER;
|
||||
return composterBlock.getContainer(cachedState, level, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack insert(ItemStack stack, boolean simulate) {
|
||||
IItemHandler handler = new SidedInvWrapper(getContainer(), Direction.UP);
|
||||
return ItemHandlerHelper.insertItem(handler, stack, simulate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack extract(int slot, int amount, boolean simulate) {
|
||||
IItemHandler handler = new SidedInvWrapper(getContainer(), Direction.DOWN);
|
||||
return handler.extractItem(slot, amount, simulate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlotCount() {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ import net.minecraft.world.item.crafting.Recipe;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.ComposterBlock;
|
||||
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
@ -148,7 +149,8 @@ public interface ItemAttribute {
|
||||
|| testRecipe(s, w, AllRecipeTypes.MILLING.getType())),
|
||||
SMELTABLE((s, w) -> testRecipe(s, w, RecipeType.SMELTING)),
|
||||
SMOKABLE((s, w) -> testRecipe(s, w, RecipeType.SMOKING)),
|
||||
BLASTABLE((s, w) -> testRecipe(s, w, RecipeType.BLASTING));
|
||||
BLASTABLE((s, w) -> testRecipe(s, w, RecipeType.BLASTING)),
|
||||
COMPOSTABLE(s -> ComposterBlock.COMPOSTABLES.containsKey(s.getItem()));
|
||||
|
||||
private static final RecipeWrapper RECIPE_WRAPPER = new RecipeWrapper(new ItemStackHandler(1));
|
||||
private Predicate<ItemStack> test;
|
||||
|
@ -84,12 +84,12 @@ public class TrainRelocationPacket extends SimplePacketBase {
|
||||
return;
|
||||
|
||||
if (!sender.position()
|
||||
.closerThan(Vec3.atCenterOf(pos), 26)) {
|
||||
.closerThan(Vec3.atCenterOf(pos), 64)) {
|
||||
Create.LOGGER.warn(messagePrefix + train.name.getString() + ": player too far from clicked pos");
|
||||
return;
|
||||
}
|
||||
if (!sender.position()
|
||||
.closerThan(cce.position(), 26 + cce.getBoundingBox()
|
||||
.closerThan(cce.position(), 64 + cce.getBoundingBox()
|
||||
.getXsize() / 2)) {
|
||||
Create.LOGGER.warn(messagePrefix + train.name.getString() + ": player too far from carriage entity");
|
||||
return;
|
||||
|
@ -29,6 +29,9 @@ import net.minecraft.world.level.Level;
|
||||
|
||||
public class ScheduleRuntime {
|
||||
|
||||
private static final int TBD = -1;
|
||||
private static final int INVALID = -2;
|
||||
|
||||
public enum State {
|
||||
PRE_TRANSIT, IN_TRANSIT, POST_TRANSIT
|
||||
}
|
||||
@ -129,7 +132,7 @@ public class ScheduleRuntime {
|
||||
destinationReached();
|
||||
return;
|
||||
}
|
||||
if (train.navigation.startNavigation(nextStation, Double.MAX_VALUE, false) != -1) {
|
||||
if (train.navigation.startNavigation(nextStation, Double.MAX_VALUE, false) != TBD) {
|
||||
state = State.IN_TRANSIT;
|
||||
ticksInTransit = 0;
|
||||
}
|
||||
@ -231,7 +234,7 @@ public class ScheduleRuntime {
|
||||
isAutoSchedule = auto;
|
||||
train.status.newSchedule();
|
||||
predictionTicks = new ArrayList<>();
|
||||
schedule.entries.forEach($ -> predictionTicks.add(-1));
|
||||
schedule.entries.forEach($ -> predictionTicks.add(TBD));
|
||||
displayLinkUpdateRequested = true;
|
||||
}
|
||||
|
||||
@ -269,8 +272,10 @@ public class ScheduleRuntime {
|
||||
if (currentStation != null)
|
||||
predictions.add(createPrediction(current, currentStation.name, currentTitle, 0));
|
||||
int departureTime = estimateStayDuration(current);
|
||||
if (departureTime == -1)
|
||||
accumulatedTime = -1;
|
||||
if (departureTime == INVALID)
|
||||
accumulatedTime = INVALID;
|
||||
else
|
||||
accumulatedTime += departureTime;
|
||||
|
||||
} else {
|
||||
GlobalStation destination = train.navigation.destination;
|
||||
@ -292,10 +297,10 @@ public class ScheduleRuntime {
|
||||
predictions.add(createPrediction(current, destination.name, currentTitle, accumulatedTime));
|
||||
|
||||
int departureTime = estimateStayDuration(current);
|
||||
if (departureTime != -1)
|
||||
if (departureTime != INVALID)
|
||||
accumulatedTime += departureTime;
|
||||
if (departureTime == -1)
|
||||
accumulatedTime = -1;
|
||||
else
|
||||
accumulatedTime = INVALID;
|
||||
|
||||
} else
|
||||
predictForEntry(current, currentTitle, accumulatedTime, predictions);
|
||||
@ -327,47 +332,56 @@ public class ScheduleRuntime {
|
||||
return accumulatedTime;
|
||||
if (predictionTicks.size() <= currentEntry)
|
||||
return accumulatedTime;
|
||||
if (accumulatedTime == -1) {
|
||||
|
||||
int departureTime = estimateStayDuration(index);
|
||||
|
||||
if (accumulatedTime < 0) {
|
||||
predictions.add(createPrediction(index, filter.getFilter(), currentTitle, accumulatedTime));
|
||||
return -1;
|
||||
return Math.min(accumulatedTime, departureTime);
|
||||
}
|
||||
|
||||
int predictedTime = predictionTicks.get(index);
|
||||
int departureTime = estimateStayDuration(index);
|
||||
accumulatedTime += predictedTime;
|
||||
|
||||
if (predictedTime == -1)
|
||||
accumulatedTime = -1;
|
||||
else {
|
||||
accumulatedTime += predictedTime;
|
||||
if (departureTime != -1)
|
||||
accumulatedTime += departureTime;
|
||||
}
|
||||
if (predictedTime == TBD)
|
||||
accumulatedTime = TBD;
|
||||
|
||||
predictions.add(createPrediction(index, filter.getFilter(), currentTitle, accumulatedTime));
|
||||
|
||||
if (departureTime == -1)
|
||||
return -1;
|
||||
|
||||
if (accumulatedTime != TBD)
|
||||
accumulatedTime += departureTime;
|
||||
|
||||
if (departureTime == INVALID)
|
||||
accumulatedTime = INVALID;
|
||||
|
||||
return accumulatedTime;
|
||||
}
|
||||
|
||||
private int estimateStayDuration(int index) {
|
||||
if (index >= schedule.entries.size()) {
|
||||
if (!schedule.cyclic)
|
||||
return 100000;
|
||||
return INVALID;
|
||||
index = 0;
|
||||
}
|
||||
|
||||
ScheduleEntry scheduleEntry = schedule.entries.get(index);
|
||||
for (List<ScheduleWaitCondition> list : scheduleEntry.conditions)
|
||||
for (ScheduleWaitCondition condition : list)
|
||||
if (condition instanceof ScheduledDelay wait)
|
||||
return wait.totalWaitTicks();
|
||||
Columns: for (List<ScheduleWaitCondition> list : scheduleEntry.conditions) {
|
||||
int total = 0;
|
||||
for (ScheduleWaitCondition condition : list) {
|
||||
if (!(condition instanceof ScheduledDelay wait))
|
||||
continue Columns;
|
||||
total += wait.totalWaitTicks();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
return 5; // TODO properly ask conditions for time prediction
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
private TrainDeparturePrediction createPrediction(int index, String destination, String currentTitle, int time) {
|
||||
if (time == INVALID)
|
||||
return null;
|
||||
|
||||
int size = schedule.entries.size();
|
||||
if (index >= size) {
|
||||
if (!schedule.cyclic)
|
||||
@ -422,7 +436,7 @@ public class ScheduleRuntime {
|
||||
|
||||
int[] readTransits = tag.getIntArray("TransitTimes");
|
||||
if (schedule != null) {
|
||||
schedule.entries.forEach($ -> predictionTicks.add(-1));
|
||||
schedule.entries.forEach($ -> predictionTicks.add(TBD));
|
||||
if (readTransits.length == schedule.entries.size())
|
||||
for (int i = 0; i < readTransits.length; i++)
|
||||
predictionTicks.set(i, readTransits[i]);
|
||||
|
@ -31,7 +31,7 @@ import net.minecraft.world.phys.Vec3;
|
||||
public class DumpRailwaysCommand {
|
||||
|
||||
static ArgumentBuilder<CommandSourceStack, ?> register() {
|
||||
return Commands.literal("dumpRailways")
|
||||
return Commands.literal("trains")
|
||||
.requires(cs -> cs.hasPermission(2))
|
||||
.executes(ctx -> {
|
||||
CommandSourceStack source = ctx.getSource();
|
||||
@ -52,7 +52,7 @@ public class DumpRailwaysCommand {
|
||||
int orange = 0xFFAD60;
|
||||
|
||||
chat.accept("", white);
|
||||
chat.accept("-+------<< Railways Summary: >>------+-", white);
|
||||
chat.accept("-+------<< Train Summary: >>------+-", white);
|
||||
int graphCount = railways.trackNetworks.size();
|
||||
chat.accept("Track Networks: " + graphCount, blue);
|
||||
chat.accept("Signal Groups: " + railways.signalEdgeGroups.size(), blue);
|
||||
|
@ -8,16 +8,15 @@ import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
||||
public abstract class SafeTileEntityRenderer<T extends BlockEntity> implements BlockEntityRenderer<T> {
|
||||
|
||||
@Override
|
||||
public final void render(T te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light,
|
||||
public final void render(T te, float partialTicks, PoseStack ms, MultiBufferSource bufferSource, int light,
|
||||
int overlay) {
|
||||
if (isInvalid(te))
|
||||
return;
|
||||
renderSafe(te, partialTicks, ms, buffer, light, overlay);
|
||||
renderSafe(te, partialTicks, ms, bufferSource, light, overlay);
|
||||
}
|
||||
|
||||
protected abstract void renderSafe(T te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light,
|
||||
protected abstract void renderSafe(T te, float partialTicks, PoseStack ms, MultiBufferSource bufferSource, int light,
|
||||
int overlay);
|
||||
|
||||
public boolean isInvalid(T te) {
|
||||
|
@ -24,6 +24,7 @@ import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
import net.minecraft.world.level.Level;
|
||||
@ -31,6 +32,7 @@ import net.minecraft.world.level.block.BaseRailBlock;
|
||||
import net.minecraft.world.level.block.BedBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.IceBlock;
|
||||
import net.minecraft.world.level.block.SlimeBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
@ -40,6 +42,7 @@ import net.minecraft.world.level.block.state.properties.SlabType;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import net.minecraftforge.common.IPlantable;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.level.BlockEvent;
|
||||
@ -155,9 +158,11 @@ public class BlockHelper {
|
||||
float effectChance, Consumer<ItemStack> droppedItemCallback) {
|
||||
FluidState fluidState = world.getFluidState(pos);
|
||||
BlockState state = world.getBlockState(pos);
|
||||
|
||||
if (world.random.nextFloat() < effectChance)
|
||||
world.levelEvent(2001, pos, Block.getId(state));
|
||||
BlockEntity tileentity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
|
||||
|
||||
if (player != null) {
|
||||
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, player);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
@ -177,9 +182,24 @@ public class BlockHelper {
|
||||
&& (player == null || !player.isCreative())) {
|
||||
for (ItemStack itemStack : Block.getDrops(state, (ServerLevel) world, pos, tileentity, player, usedTool))
|
||||
droppedItemCallback.accept(itemStack);
|
||||
|
||||
// Simulating IceBlock#playerDestroy. Not calling method directly as it would drop item
|
||||
// entities as a side-effect
|
||||
if (state.getBlock() instanceof IceBlock && usedTool.getEnchantmentLevel(Enchantments.SILK_TOUCH) == 0) {
|
||||
if (world.dimensionType()
|
||||
.ultraWarm())
|
||||
return;
|
||||
|
||||
Material material = world.getBlockState(pos.below())
|
||||
.getMaterial();
|
||||
if (material.blocksMotion() || material.isLiquid())
|
||||
world.setBlockAndUpdate(pos, Blocks.WATER.defaultBlockState());
|
||||
return;
|
||||
}
|
||||
|
||||
state.spawnAfterBreak((ServerLevel) world, pos, ItemStack.EMPTY, true);
|
||||
}
|
||||
|
||||
|
||||
world.setBlockAndUpdate(pos, fluidState.createLegacyBlock());
|
||||
}
|
||||
|
||||
|
@ -414,8 +414,10 @@
|
||||
"create.item_attributes.smeltable.inverted": "cannot be Smelted",
|
||||
"create.item_attributes.smokable": "can be Smoked",
|
||||
"create.item_attributes.smokable.inverted": "cannot be Smoked",
|
||||
"create.item_attributes.blastable": "is smeltable in Blast Furnace",
|
||||
"create.item_attributes.blastable.inverted": "is not smeltable in Blast Furnace",
|
||||
"create.item_attributes.blastable": "can be Smelted in a Blast Furnace",
|
||||
"create.item_attributes.blastable.inverted": "cannot be Smelted in a Blast Furnace",
|
||||
"create.item_attributes.compostable": "can be composted",
|
||||
"create.item_attributes.compostable.inverted": "cannot be composted",
|
||||
|
||||
"create.item_attributes.shulker_level": "is shulker %1$s",
|
||||
"create.item_attributes.shulker_level.inverted": "is shulker not %1$s",
|
||||
|
@ -2,7 +2,7 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "forge:mod_loaded",
|
||||
"modid": "appliedenergistics2"
|
||||
"modid": "ae2"
|
||||
}
|
||||
],
|
||||
"type": "create:milling",
|
||||
@ -13,7 +13,7 @@
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "appliedenergistics2:certus_quartz_dust",
|
||||
"item": "ae2:certus_quartz_dust",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
|
@ -2,7 +2,7 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "forge:mod_loaded",
|
||||
"modid": "appliedenergistics2"
|
||||
"modid": "ae2"
|
||||
}
|
||||
],
|
||||
"type": "create:milling",
|
||||
@ -13,7 +13,7 @@
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "appliedenergistics2:ender_dust",
|
||||
"item": "ae2:ender_dust",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
|
@ -2,18 +2,18 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "forge:mod_loaded",
|
||||
"modid": "appliedenergistics2"
|
||||
"modid": "ae2"
|
||||
}
|
||||
],
|
||||
"type": "create:milling",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "appliedenergistics2:fluix_crystal"
|
||||
"item": "ae2:fluix_crystal"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "appliedenergistics2:fluix_dust",
|
||||
"item": "ae2:fluix_dust",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
|
@ -1,21 +0,0 @@
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"type": "forge:mod_loaded",
|
||||
"modid": "appliedenergistics2"
|
||||
}
|
||||
],
|
||||
"type": "create:milling",
|
||||
"ingredients": [
|
||||
{
|
||||
"tag": "forge:ingots/gold"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "appliedenergistics2:gold_dust",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"processingTime": 100
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"type": "forge:mod_loaded",
|
||||
"modid": "appliedenergistics2"
|
||||
}
|
||||
],
|
||||
"type": "create:milling",
|
||||
"ingredients": [
|
||||
{
|
||||
"tag": "forge:ingots/iron"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "appliedenergistics2:iron_dust",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"processingTime": 200
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"type": "forge:mod_loaded",
|
||||
"modid": "appliedenergistics2"
|
||||
}
|
||||
],
|
||||
"type": "create:milling",
|
||||
"ingredients": [
|
||||
{
|
||||
"tag": "forge:gems/quartz"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "appliedenergistics2:nether_quartz_dust",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"processingTime": 200
|
||||
}
|
@ -2,18 +2,18 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "forge:mod_loaded",
|
||||
"modid": "appliedenergistics2"
|
||||
"modid": "ae2"
|
||||
}
|
||||
],
|
||||
"type": "create:milling",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "appliedenergistics2:sky_stone_block"
|
||||
"item": "ae2:sky_stone_block"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "appliedenergistics2:sky_dust",
|
||||
"item": "ae2:sky_dust",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
|
@ -2,7 +2,7 @@
|
||||
"conditions": [
|
||||
{
|
||||
"type": "forge:mod_loaded",
|
||||
"modid": "appliedenergistics2"
|
||||
"modid": "ae2"
|
||||
}
|
||||
],
|
||||
"type": "create:mixing",
|
||||
@ -16,7 +16,7 @@
|
||||
"amount": 250
|
||||
},
|
||||
{
|
||||
"item": "appliedenergistics2:charged_certus_quartz_crystal"
|
||||
"item": "ae2:charged_certus_quartz_crystal"
|
||||
},
|
||||
{
|
||||
"tag": "forge:gems/quartz"
|
||||
@ -24,7 +24,7 @@
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "appliedenergistics2:fluix_crystal",
|
||||
"item": "ae2:fluix_crystal",
|
||||
"count": 2
|
||||
}
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user