From ca2cf9457965c7235ccf7fffbdd6792bacf17055 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Mon, 8 Mar 2021 02:59:43 +0100 Subject: [PATCH] Scene hacking getting out of control - New highly over-engineered scenes for Encased Fans - Potential Fix for GL errors with the framebuffer system --- .../components/fan/EncasedFanTileEntity.java | 4 +- .../create/foundation/gui/UIRenderHelper.java | 3 +- .../foundation/ponder/SceneBuilder.java | 16 + .../foundation/ponder/content/FanScenes.java | 297 ++++++++++++++++++ .../ponder/content/PonderIndex.java | 5 + .../ponder/elements/ParrotElement.java | 40 ++- src/main/resources/ponder/fan/direction.nbt | Bin 0 -> 657 bytes src/main/resources/ponder/fan/processing.nbt | Bin 0 -> 1098 bytes src/main/resources/ponder/fan/source.nbt | Bin 0 -> 533 bytes 9 files changed, 358 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/simibubi/create/foundation/ponder/content/FanScenes.java create mode 100644 src/main/resources/ponder/fan/direction.nbt create mode 100644 src/main/resources/ponder/fan/processing.nbt create mode 100644 src/main/resources/ponder/fan/source.nbt diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java index 132f9f65d..eb5bc626c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java @@ -171,7 +171,9 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements public void tick() { super.tick(); - if (!world.isRemote && airCurrentUpdateCooldown-- <= 0) { + boolean server = !world.isRemote || isVirtual(); + + if (server && airCurrentUpdateCooldown-- <= 0) { airCurrentUpdateCooldown = AllConfigs.SERVER.kinetics.fanBlockCheckRate.get(); updateAirFlow = true; } diff --git a/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java b/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java index a4b4a22f5..f6db492b5 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java @@ -21,7 +21,8 @@ public class UIRenderHelper { RenderSystem.recordRenderCall(() -> { MainWindow mainWindow = Minecraft.getInstance().getWindow(); framebuffer = new Framebuffer(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), true, Minecraft.IS_RUNNING_ON_MAC); - framebuffer.deleteFramebuffer(); + framebuffer.setFramebufferColor(0, 0, 0, 0); +// framebuffer.deleteFramebuffer(); }); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java index b8d55dead..fe208b5ff 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java @@ -317,6 +317,14 @@ public class SceneBuilder { addInstruction(scene -> scene.linkElement(parrot, link)); return link; } + + public ElementLink flappyBirb(Vec3d location) { + ElementLink link = new ElementLink<>(ParrotElement.class); + ParrotElement parrot = ParrotElement.flappy(location); + addInstruction(new CreateParrotInstruction(10, Direction.DOWN, parrot)); + addInstruction(scene -> scene.linkElement(parrot, link)); + return link; + } public ElementLink birbPartying(Vec3d location) { ElementLink link = new ElementLink<>(ParrotElement.class); @@ -566,6 +574,14 @@ public class SceneBuilder { resolve.ifPresent(tis -> tis.locked = stalled); }); } + + public void changeBeltItemTo(ElementLink link, ItemStack newStack) { + addInstruction(scene -> { + BeltItemElement resolve = scene.resolve(link); + if (resolve != null) + resolve.ifPresent(tis -> tis.stack = newStack); + }); + } public void setKineticSpeed(Selection selection, float speed) { modifyKineticSpeed(selection, f -> speed); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/FanScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/FanScenes.java new file mode 100644 index 000000000..8d52c8113 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/FanScenes.java @@ -0,0 +1,297 @@ +package com.simibubi.create.foundation.ponder.content; + +import com.simibubi.create.AllItems; +import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; +import com.simibubi.create.content.logistics.block.depot.DepotTileEntity; +import com.simibubi.create.foundation.ponder.ElementLink; +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; +import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.elements.BeltItemElement; +import com.simibubi.create.foundation.ponder.elements.EntityElement; +import com.simibubi.create.foundation.ponder.elements.InputWindowElement; +import com.simibubi.create.foundation.ponder.elements.ParrotElement; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.ponder.instructions.EmitParticlesInstruction.Emitter; +import com.simibubi.create.foundation.utility.Pointing; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +public class FanScenes { + + public static void direction(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("fan_direction", "Air flow of Encased Fans"); + scene.configureBasePlate(0, 1, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); +// scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -f); + scene.idle(5); + scene.world.showSection(util.select.fromTo(3, 1, 0, 3, 1, 5) + .add(util.select.position(3, 2, 4)), Direction.DOWN); + scene.world.showSection(util.select.fromTo(2, 1, 5, 1, 1, 5), Direction.DOWN); + scene.idle(10); + + BlockPos fanPos = util.grid.at(1, 1, 4); + scene.world.showSection(util.select.position(fanPos), Direction.SOUTH); + + scene.idle(40); + scene.effects.rotationDirectionIndicator(fanPos.south()); + + ElementLink flappyBirb = scene.special.flappyBirb(util.vector.topOf(1, 0, 3)); + scene.idle(2); + scene.special.rotateParrot(flappyBirb, 0, 235, 0, 30); + scene.special.moveParrot(flappyBirb, util.vector.of(0, 0, -2.5), 30); + scene.idle(20); + + scene.overlay.showText(80) + .text("Encased Fans use Rotational Force to create an Air Current") + .placeNearTarget() + .pointAt(util.vector.topOf(fanPos)); + scene.idle(90); + + BlockPos leverPos = util.grid.at(3, 2, 4); + Selection reverse = util.select.fromTo(3, 1, 5, 1, 1, 4); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reverse, f -> -f); + scene.effects.rotationDirectionIndicator(fanPos.south()); + scene.special.rotateParrot(flappyBirb, 0, 215 * 2, 0, 30); + scene.special.moveParrot(flappyBirb, util.vector.of(0, 0, 2.5), 30); + scene.idle(31); + + scene.overlay.showText(60) + .text("Strength and Direction of Flow depends on the Rotational Input") + .placeNearTarget() + .pointAt(util.vector.topOf(fanPos)); + scene.markAsFinished(); + scene.idle(70); + + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reverse, f -> -f); + scene.world.modifyKineticSpeed(util.select.everywhere(), f -> 4 * f); + scene.effects.rotationSpeedIndicator(fanPos.south()); + scene.special.rotateParrot(flappyBirb, 0, 245 * 4, 0, 30); + scene.special.moveParrot(flappyBirb, util.vector.of(0, 0, -20), 30); + + } + + public static void processing(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("fan_processing", "Processing Items using Encased Fans"); + scene.configureBasePlate(1, 0, 5); + scene.world.showSection(util.select.layer(0) + .substract(util.select.position(0, 0, 4)), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.fromTo(6, 1, 2, 5, 1, 2) + .add(util.select.position(1, 1, 2)), Direction.DOWN); + scene.idle(25); + + BlockPos blockPos = util.grid.at(4, 1, 2); + + // blasting start + + ElementLink blockInFront = + scene.world.showIndependentSection(util.select.position(3, 1, 0), Direction.SOUTH); + scene.world.moveSection(blockInFront, util.vector.of(1, 0, 2), 0); + scene.world.setBlock(blockPos, Blocks.LAVA.getDefaultState(), false); + scene.idle(10); + + scene.overlay.showSelectionWithText(util.select.fromTo(blockPos, blockPos.west(2)), 80) + .colored(PonderPalette.RED) + .text("When passing through lava, the Air Flow becomes Heated"); + scene.idle(80); + + ItemStack stack = new ItemStack(Items.GOLD_ORE); + ItemStack smelted = new ItemStack(Items.GOLD_INGOT); + + ElementLink entityLink = scene.world.createItemEntity(util.vector.centerOf(blockPos.west(2) + .up(2)), util.vector.of(0, 0.1, 0), stack); + scene.idle(15); + scene.world.modifyEntity(entityLink, e -> e.setMotion(-0.2f, 0, 0)); + Vec3d itemVec = util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.EAST) + .add(0.1, 0, 0); + scene.overlay.showControls(new InputWindowElement(itemVec, Pointing.DOWN).withItem(stack), 20); + scene.idle(20); + scene.effects.emitParticles(itemVec.add(0, 0.2f, 0), Emitter.simple(ParticleTypes.LARGE_SMOKE, Vec3d.ZERO), 1, + 60); + + scene.overlay.showText(80) + .colored(PonderPalette.WHITE) + .pointAt(itemVec) + .placeNearTarget() + .text("Items caught in the area will be smelted"); + + scene.idle(60); + scene.world.modifyEntities(ItemEntity.class, ie -> ie.setItem(smelted)); + scene.idle(40); + scene.overlay.showControls(new InputWindowElement(itemVec, Pointing.DOWN).withItem(smelted), 20); + scene.idle(20); + scene.world.modifyEntities(ItemEntity.class, Entity::remove); + scene.idle(20); + + scene.overlay.showText(80) + .colored(PonderPalette.RED) + .pointAt(itemVec) + .placeNearTarget() + .text("Food items thrown here would be incinerated"); + scene.idle(40); + + // smoking start + + BlockState campfire = Blocks.FIRE.getDefaultState(); + scene.world.hideIndependentSection(blockInFront, Direction.NORTH); + scene.idle(15); + scene.world.setBlock(util.grid.at(3, 1, 0), campfire, false); + scene.world.setBlock(blockPos, campfire, true); + blockInFront = scene.world.showIndependentSection(util.select.position(3, 1, 0), Direction.NORTH); + scene.world.moveSection(blockInFront, util.vector.of(1, 0, 2), 0); + scene.idle(50); + + scene.overlay.showSelectionWithText(util.select.fromTo(blockPos, blockPos.west(2)), 60) + .colored(PonderPalette.BLACK) + .text("Instead, a setup for Smoking using Fire should be used for them"); + scene.idle(80); + + // washing start + + BlockState water = Blocks.WATER.getDefaultState(); + scene.world.hideIndependentSection(blockInFront, Direction.NORTH); + scene.idle(15); + scene.world.setBlock(util.grid.at(3, 1, 0), water, false); + scene.world.setBlock(blockPos, water, true); + blockInFront = scene.world.showIndependentSection(util.select.position(3, 1, 0), Direction.NORTH); + scene.world.moveSection(blockInFront, util.vector.of(1, 0, 2), 0); + scene.idle(20); + + scene.overlay.showSelectionWithText(util.select.fromTo(blockPos, blockPos.west(2)), 60) + .colored(PonderPalette.MEDIUM) + .text("Air Flows passing through water create a Washing Setup"); + scene.idle(70); + + stack = AllItems.CRUSHED_GOLD.asStack(); + ItemStack washed = new ItemStack(Items.GOLD_NUGGET, 16); + + entityLink = scene.world.createItemEntity(util.vector.centerOf(blockPos.west(2) + .up(2)), util.vector.of(0, 0.1, 0), stack); + scene.idle(15); + scene.world.modifyEntity(entityLink, e -> e.setMotion(-0.2f, 0, 0)); + scene.overlay.showControls(new InputWindowElement(itemVec, Pointing.DOWN).withItem(stack), 20); + scene.idle(20); + scene.effects.emitParticles(itemVec.add(0, 0.2f, 0), Emitter.simple(ParticleTypes.SPIT, Vec3d.ZERO), 1, 60); + + scene.overlay.showText(50) + .colored(PonderPalette.WHITE) + .pointAt(itemVec) + .placeNearTarget() + .text("Some interesting new processing can be done with it"); + + scene.idle(60); + scene.world.modifyEntities(ItemEntity.class, ie -> ie.setItem(washed)); + scene.overlay.showControls(new InputWindowElement(itemVec, Pointing.DOWN).withItem(washed), 20); + scene.idle(20); + scene.world.modifyEntities(ItemEntity.class, Entity::remove); + scene.idle(20); + + scene.overlay.showText(100) + .colored(PonderPalette.RED) + .pointAt(util.vector.topOf(blockPos.east())) + .placeNearTarget() + .text("The Speed of the Fan does NOT affect the processing speed, only its range"); + scene.world.destroyBlock(util.grid.at(1, 1, 2)); + scene.idle(110); + + ElementLink cogs = scene.world.makeSectionIndependent(util.select.fromTo(6, 1, 2, 6, 0, 3) + .add(util.select.fromTo(4, 0, 2, 5, 0, 2))); + scene.world.modifyKineticSpeed(util.select.position(5, 2, 2), f -> f / 3f); + scene.world.moveSection(cogs, util.vector.of(0, 1, 0), 15); + scene.world.moveSection(blockInFront, util.vector.of(0, 1, 0), 15); + scene.world.destroyBlock(blockPos.east()); + scene.world.showSection(util.select.position(blockPos.east() + .up()), Direction.DOWN); + scene.world.setBlock(blockPos.up(), Blocks.WATER.getDefaultState(), false); + + ItemStack sand = new ItemStack(Items.SAND); + ItemStack clay = new ItemStack(Items.CLAY_BALL); + + scene.idle(20); + BlockPos depos = util.grid.at(3, 4, 2); + ElementLink depot = + scene.world.showIndependentSection(util.select.position(depos), Direction.DOWN); + scene.world.moveSection(depot, util.vector.of(-1, -3, 0), 0); + scene.world.createItemOnBeltLike(depos, Direction.NORTH, sand); + scene.idle(10); + Vec3d depotTop = util.vector.topOf(2, 1, 2) + .add(0, 0.25, 0); + scene.effects.emitParticles(depotTop, Emitter.simple(ParticleTypes.SPIT, Vec3d.ZERO), .5f, 30); + scene.idle(30); + scene.world.modifyTileNBT(util.select.position(depos), DepotTileEntity.class, + nbt -> nbt.put("HeldItem", new TransportedItemStack(clay).serializeNBT())); + scene.effects.emitParticles(depotTop, Emitter.simple(ParticleTypes.SPIT, Vec3d.ZERO), .5f, 30); + scene.overlay.showText(90) + .pointAt(depotTop) + .text("Fan Processing can also be applied to Items on Depots and Belts"); + + scene.idle(100); + scene.world.moveSection(depot, util.vector.of(-1, 0, 0), 15); + scene.idle(15); + ElementLink largeCog = + scene.world.showIndependentSection(util.select.position(1, 2, 4), Direction.UP); + ElementLink belt = + scene.world.showIndependentSection(util.select.fromTo(3, 3, 1, 1, 3, 3), Direction.DOWN); + scene.world.moveSection(largeCog, util.vector.of(-1, -2, 0), 0); + scene.world.moveSection(belt, util.vector.of(-1, -2, 0), 0); + ElementLink transported = + scene.world.createItemOnBelt(util.grid.at(3, 3, 3), Direction.SOUTH, sand); + scene.idle(60); + scene.effects.emitParticles(depotTop, Emitter.simple(ParticleTypes.SPIT, Vec3d.ZERO), .5f, 25); + scene.idle(25); + scene.world.changeBeltItemTo(transported, new ItemStack(Items.CLAY_BALL)); + scene.effects.emitParticles(depotTop, Emitter.simple(ParticleTypes.SPIT, Vec3d.ZERO), .5f, 25); + scene.idle(60); + + scene.world.setKineticSpeed(util.select.position(1, 2, 4) + .add(util.select.fromTo(3, 3, 1, 1, 3, 3)), 0); + + } + + public static void source(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("fan_source", "Generating Rotational Force using Encased Fans"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layer(1), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.layersFrom(2), Direction.DOWN); + scene.idle(10); + BlockPos rightFan = util.grid.at(1, 2, 2); + scene.overlay.showText(80) + .text("Fans facing down into a source of heat can provide Rotational Force") + .placeNearTarget() + .pointAt(util.vector.blockSurface(rightFan, Direction.WEST)); + scene.idle(80); + + for (BlockPos pos : new BlockPos[] { rightFan, util.grid.at(3, 2, 2) }) { + scene.idle(10); + scene.world.toggleRedstonePower(util.select.position(pos.north())); + scene.effects.indicateRedstone(pos.north()); + scene.world.setKineticSpeed(util.select.fromTo(pos, pos.up()), 4); + scene.effects.rotationSpeedIndicator(pos.up()); + } + + scene.overlay.showText(90) + .text("When given a Redstone Signal, the Fans will start providing power") + .colored(PonderPalette.RED) + .placeNearTarget() + .pointAt(util.vector.blockSurface(rightFan, Direction.WEST)); + scene.markAsFinished(); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java index ffc35cb0c..63ad820b8 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java @@ -41,6 +41,11 @@ public class PonderIndex { PonderRegistry.addStoryBoard(AllBlocks.CLUTCH, "clutch", KineticsScenes::clutch); PonderRegistry.addStoryBoard(AllBlocks.GEARSHIFT, "gearshift", KineticsScenes::gearshift); + PonderRegistry.forComponents(AllBlocks.ENCASED_FAN) + .addStoryBoard("fan/direction", FanScenes::direction) + .addStoryBoard("fan/processing", FanScenes::processing) + .addStoryBoard("fan/source", FanScenes::source); + PonderRegistry.addStoryBoard(AllBlocks.CREATIVE_MOTOR, "creative_motor", KineticsScenes::creativeMotor); PonderRegistry.addStoryBoard(AllBlocks.WATER_WHEEL, "water_wheel", KineticsScenes::waterWheel); PonderRegistry.addStoryBoard(AllBlocks.HAND_CRANK, "hand_crank", KineticsScenes::handCrank); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java index 38bc429ed..abcbfd691 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java @@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderWorld; import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.client.Minecraft; @@ -42,6 +43,12 @@ public class ParrotElement extends AnimatedSceneElement { return parrotElement; } + public static ParrotElement flappy(Vec3d location) { + ParrotElement parrotElement = new ParrotElement(location); + parrotElement.pose = parrotElement.new FlappyPose(); + return parrotElement; + } + protected ParrotElement(Vec3d location) { this.location = location; } @@ -61,18 +68,19 @@ public class ParrotElement extends AnimatedSceneElement { if (entity == null) return; - entity.prevPosX = entity.getX(); - entity.prevPosY = entity.getY(); - entity.prevPosZ = entity.getZ(); entity.ticksExisted++; entity.prevRotationYawHead = entity.rotationYawHead; entity.oFlapSpeed = entity.flapSpeed; entity.oFlap = entity.flap; entity.onGround = true; - entity.prevRotationYaw = entity.rotationYaw; - entity.prevRotationPitch = entity.rotationPitch; pose.tick(scene); + + entity.prevPosX = entity.getX(); + entity.prevPosY = entity.getY(); + entity.prevPosZ = entity.getZ(); + entity.prevRotationYaw = entity.rotationYaw; + entity.prevRotationPitch = entity.rotationPitch; } public void setPositionOffset(Vec3d position, boolean immediate) { @@ -153,6 +161,28 @@ public class ParrotElement extends AnimatedSceneElement { } + class FlappyPose extends ParrotPose { + + @Override + void create(PonderWorld world) { + super.create(world); + } + + @Override + void tick(PonderScene scene) { + double length = entity.getPositionVec() + .subtract(entity.prevPosX, entity.prevPosY, entity.prevPosZ) + .length(); + entity.onGround = false; + double phase = Math.min(length * 15, 8); + float f = (float) ((AnimationTickHolder.getTicks() % 100) * phase); + entity.flapSpeed = MathHelper.sin(f) + 1; + if (length == 0) + entity.flapSpeed = 0; + } + + } + class SpinOnComponentPose extends ParrotPose { private BlockPos componentPos; diff --git a/src/main/resources/ponder/fan/direction.nbt b/src/main/resources/ponder/fan/direction.nbt new file mode 100644 index 0000000000000000000000000000000000000000..08e9d02360fcc06c86c6e3dca379632cc8cd40ac GIT binary patch literal 657 zcmV;C0&e{uiwFP!000000M(b#ZqqOnhEHNUO|wZ%2qa#BhuE&zKmu+iqzMGvR9-#Zu+AI_I^0;{#{lDZKw5Y|bDZN_p;)DshVF>wHg1#ox(ryKDGPSg|Q zbK(FF3*hhoPB&OUomoJgH*r`1hX-)F!2{~d1M0kq!vZ)wfYS{TP-hWP=S>_Iz~Q}| z3|MvQ1c;Lwu{gYF^7fADt-bu>V_i^Wl)>N_-9nq0fb_MjWv<-McNYzqpU@AVK)W2` z_XVY2K=Nl_Kyu;?T6;u6kV32qc%B<1*nw5^y2Q~;Rp?ZnQKbHEa%vvY=d0~SUufQ^ z`76zOUF~5>N9^hN4UevadpfE<&mvC;+de;%yZjKX9m{=^Z=WBm)p2l_AImz#_Ul;j zqtg-pUpne_I@km05U_Jt6j)sC|JCKGU8^jD>@8Mkq*K+T)%mp5iB&Ew7NfDOe36kS z()K+7BDnn^N&cl-d##8GN@J&L?C$dE+d7|?B@DLjyv3nbhz@r=Lj$6w3FP(u{&5ymBUf4E7~e0brH{Q zB5b7>qszMrl`i{Wbd9FD#-y;bpmj{CClf3{jAdz&^5vPb5S?G6x+0X)Oq!J@iz#Ax zKh~3$bsx&vgY0Oxvv^9i@)60HjtzB5QEB6**Ev1y($5^!dVyxs!Yl2{M{rskDZkX( r^Z>iPag^5G6!^yX5`UnfbG7qEI{68WRhs@Oq`%-Vqi$0v<_-V={0u@n literal 0 HcmV?d00001 diff --git a/src/main/resources/ponder/fan/processing.nbt b/src/main/resources/ponder/fan/processing.nbt new file mode 100644 index 0000000000000000000000000000000000000000..00de4c3fe8b98d8e62f3142c03be41c846260545 GIT binary patch literal 1098 zcmV-Q1hxAgiwFP!000000L@t2Zrer>9o}@IIf)Y79JLk-t*(H5|F1RYXMF#-V zvrVU$o?Yl*tRo$vg7oM@>w=5mQu*}fhb}mYP{kk%^1}g7X{IqBQMR#bY^;inW8lX% z@Z%ZAV^wVIicQPFroe9Ph{vw6sm9|N_;C&Vcm{roxUC(yJOi5oyKRtn+aT||{I~{w zJOe*gewJ;V23(FoP91}s?(*Xr`0)(<6fwI7xo{0~vCEHZ;K!@=3|)D@XaiWF_3Jmj{-JJ#*xGx^any*M)BmgXqI)Mwf2jn2Zx1;(2O_Q)x=-bwVTK0 zfp?xDhJR-^&ra#5%5MCggk+h@VHk&aozm%pKM=8&f^(D(SbspK7wb>DzM$)0biE;f ztpQUMBesO2?dYVS;L;Dorjv|$ik2LnK>Pjkb+iM>65zkV7$wsweR-wiv11%Ch2dz-;wq(X zPU+E_(uU?%ZUU`6g4_XV1>(CLgoL_T!@qArN4GUBmNBdvl*eWEuIaxH% z@_4VwI^LBmd#}l=f;`AT7LQ*qcfxd_cOIn5e8>1ab#StR+RvfRgchXu@+GK*iyz^jG~{Ev$F zOcbA0VF^diu#)zYNdp`-{H`ME+q!L-Q^8T~Twf867ft!FYjE@*uWZaQ1p6vg=aFP$m#@JCH9~~?8#%g{yks~UB4dM zy{_**-1Q-^kMb7y$sQr>sm4E#EVH~x_^vl9whf15x z5We5M5G303 zre8Zc&|6S!l8ea%L-59oE2Nt$n#7Ec(l?X!O@~JsTrKDHyEUd9rOHI6^m?wE_nPW- ztzaeT!l|1uslmZG+&J}OA@#IFym1-`{#3~5mSoNNdZw)1n?#ZV7IlE#H4=8CfBP?yaKQqnVp;VEG Qsk42A&tS6wsqM3SOHq^hpYNaXIB^Y7f$-`HIRNxmNtftv)5FIKcx(MRC=L##4>I5>VyIyW4I62S3=YrWhz!nouo(_ZXvUl(gTpg8B9p^L znqs1^BBK{W4WFoMj>8k0sb0)+ic?O-OkE;F6WgBAQ=ZY&IS$X@h)fO}X{PED89fyl z@7ElMXK+N4Qv)~aP(t~wMclwK?#&(D`r{wp+YKohgZc{^bTTNjgC!Jd18*CLG5{2=RP5JL_c+w`l#>216Vq#V1 zGz?z8saF%beyCZJ=Bkw%L%{x!sg@w_c6+y30pvLaHJ)(Y*G}$AFPHMfRg|i*H0q&e!X{-zT3-nT$ z#>d1;p!6X^N^c)1I6gkJV#XZ~w8cXk@44I|uuswT)x~wI9F9%PJ{3I?pyi{a{c`SJu#8`3-*n`Tkptya)gQy}1Vu literal 0 HcmV?d00001