Skip to content

Gameplay Changes

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());
            }
        }
    }

}