Gameplay Changes
Banner Duplicate Recipe
The banner pattern limit for duplication was increased from 6 to 12.
class BannerDuplicateRecipe {
@Override
public boolean matches(CraftingInput input, Level level) {
if (input.ingredientCount() != 2) {
return false;
}
DyeColor dyeColor = null;
boolean blankBannerFound = false;
boolean patternedBannerFound = false;
for (int i = 0; i < input.size(); i++) {
ItemStack item = input.getItem(i);
if (item.isEmpty()) continue;
if (!(item.getItem() instanceof BannerItem bannerItem)) {
return false;
}
if (dyeColor == null) {
dyeColor = bannerItem.getColor();
} else if (dyeColor != bannerItem.getColor()) {
return false;
}
int size = item.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY).layers().size();
if (size > 12) {
return false;
}
if (size > 0) {
if (patternedBannerFound) return false;
patternedBannerFound = true;
} else {
if (blankBannerFound) return false;
blankBannerFound = true;
}
}
return patternedBannerFound && blankBannerFound;
}
@Override
public ItemStack assemble(CraftingInput input, HolderLookup.Provider registries) {
for (int i = 0; i < input.size(); i++) {
ItemStack item = input.getItem(i);
if (!item.isEmpty()) {
int size = item.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY).layers().size();
if (size > 0 && size <= 12) {
return item.copyWithCount(1);
}
}
}
return ItemStack.EMPTY;
}
}
Boat Passenger Eject
Boats no longer eject players after being underwater for too long. This fixes cases where players were thrown out while moving upwards in large water areas.
class AbstractBoat {
@Override
public void tick() {
this.oldStatus = this.status;
this.status = this.getStatus();
if (this.status != AbstractBoat.Status.UNDER_WATER && this.status != AbstractBoat.Status.UNDER_FLOWING_WATER) {
this.outOfControlTicks = 0.0F;
} else {
this.outOfControlTicks++;
}
if (!this.level().isClientSide && this.outOfControlTicks >= 60.0F) {
this.outOfControlTicks = 0.0F;
// this.ejectPassengers();
}
super.tick();
}
}
Thrown Enderpearl
Ender pearls no longer deal damage after teleport.
class ThrownEnderpearl {
@Override
protected void onHit(HitResult hitResult) {
super.onHit(hitResult);
Level world = this.level();
if (world instanceof ServerLevel worldserver) {
if (!this.isRemoved()) {
Entity entity = this.getOwner();
if (entity != null && ThrownEnderpearl.isAllowedToTeleportOwner(entity, worldserver)) {
if (entity instanceof ServerPlayer entityplayer) {
entity.resetFallDistance();
entityplayer.resetCurrentImpulseContext();
// Mixel start
// entity.hurt(this.damageSources().fall().customEventDamager(this), 5.0F);
// Mixel end
this.playSound(worldserver, this.position());
}
this.discard(EntityRemoveEvent.Cause.HIT);
return;
}
this.discard(EntityRemoveEvent.Cause.HIT);
}
}
}
}
End Crystal Piston Push
End crystals cannot be pushed by pistons.
class EndCrystal {
private int teleportX = -1;
private boolean executeTeleport = false;
@Override
public PushReaction getPistonPushReaction() {
if (!executeTeleport) {
executeTeleport = true;
teleportX = 0;
}
return PushReaction.IGNORE;
}
}
Armor Stand Piston Push
Armor stands with certain properties ignore piston movement. This is used for some internal features.
class ArmorStand {
@Override
public PushReaction getPistonPushReaction() {
return this.isMarker() || this.isInvisible()
|| this.isDisabled(net.minecraft.world.entity.EquipmentSlot.HEAD)
|| this.isDisabled(net.minecraft.world.entity.EquipmentSlot.CHEST)
|| this.isDisabled(net.minecraft.world.entity.EquipmentSlot.LEGS)
|| this.isDisabled(net.minecraft.world.entity.EquipmentSlot.FEET)
|| this.isDisabled(net.minecraft.world.entity.EquipmentSlot.MAINHAND)
|| this.isDisabled(net.minecraft.world.entity.EquipmentSlot.OFFHAND)
? PushReaction.IGNORE
: super.getPistonPushReaction();
}
}
Golem Spawn Fix
Prevents accidental snow or iron golem spawning caused by horizontal placement.
class CarvedPumpkinBlock {
private void trySpawnGolem(Level world, BlockPos pos) {
BlockPattern orCreateSnowGolemFull = this.getOrCreateSnowGolemFull();
BlockPattern.BlockPatternMatch match = orCreateSnowGolemFull.find(world, pos);
if (match != null) {
int height = orCreateSnowGolemFull.getHeight();
int x = 0;
int z = 0;
for (int i = 0; i < height; i++) {
BlockInWorld block = match.getBlock(0, i, 0);
BlockPos currentPos = block.getPos();
if (i == 0) {
x = currentPos.getX();
z = currentPos.getZ();
} else {
if (currentPos.getX() != x) return;
if (currentPos.getZ() != z) return;
}
}
SnowGolem snowGolem = (SnowGolem) EntityType.SNOW_GOLEM.create(world);
if (snowGolem != null) {
CarvedPumpkinBlock.spawnGolemInWorld(world, match, snowGolem, match.getBlock(0, 2, 0).getPos());
}
}
}
}