Skip to content

Instantly share code, notes, and snippets.

@johnaqu1no
Created October 23, 2025 04:37
Show Gist options
  • Select an option

  • Save johnaqu1no/a6c164568f3fc66bc61dc9ecc37f1f1f to your computer and use it in GitHub Desktop.

Select an option

Save johnaqu1no/a6c164568f3fc66bc61dc9ecc37f1f1f to your computer and use it in GitHub Desktop.
SpacePotato's Found Footage Camera Code - Lectern Distribution
package gg.lode.lectern.effects.impl.horror.backrooms;
import gg.lode.lectern.effects.Effect;
import gg.lode.lectern.effects.EffectManager;
import gg.lode.lectern.effects.impl.CameraModifier;
import gg.lode.lectern.effects.impl.KeybindDisabler;
import gg.lode.lectern.events.Subscribe;
import gg.lode.lectern.events.impl.NetworkEvent;
import gg.lode.lectern.events.impl.TickEvent;
import lombok.Getter;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
public class BackroomsCutscene extends Effect {
private static final int PAUSE_DURATION = 2900;
private static final int FALL_DURATION = 7000;
private static final int END_DURATION = 5000;
// private Entity camera;
private final MinecraftClient client;
private boolean previousViewBob = false;
private boolean started;
private boolean falling;
private long startTime;
private boolean ending;
@Getter
private boolean blackScreen;
private long blackScreenStartTime;
private long blackScreenDuration;
private boolean shouldPauseSounds;
@Getter
private float cameraRoll;
private boolean hasInitializedLocation;
private double iy, ix, iz;
public BackroomsCutscene() {
super("backrooms_cutscene");
this.client = MinecraftClient.getInstance();
this.started = false;
this.falling = false;
this.ending = false;
this.blackScreen = false;
this.hasInitializedLocation = false;
}
@Subscribe
public void onNetworkEvent(NetworkEvent event) {
if (getName().equals(event.getEventId())) {
switch (event.getData().readString()) {
case "START" -> startCutscene();
case "STOP" -> stopCutscene();
}
}
}
@Subscribe
public void onTick(TickEvent event) {
if (!isActive()) return;
if (!hasInitializedLocation && client.player != null) {
this.ix = client.player.getX();
this.iy = client.player.getY();
this.iz = client.player.getZ();
hasInitializedLocation = true;
}
tickBlackScreen();
if (client.player == null || client.world == null) {
stopCutscene();
return;
}
if (!ending && !falling) {
handlePause();
} else if (falling && !ending) {
handleFall();
} else {
handleEnding();
}
}
public void startCutscene() {
setActive(true);
this.started = true;
this.falling = false;
this.ending = false;
this.startTime = System.currentTimeMillis();
showBlackScreen(60, true);
KeybindDisabler keybindDisabler = EffectManager.getEffect(KeybindDisabler.class);
if (keybindDisabler != null) {
keybindDisabler.setActive(true);
keybindDisabler.addDisabledKey(mc.options.forwardKey);
keybindDisabler.addDisabledKey(mc.options.leftKey);
keybindDisabler.addDisabledKey(mc.options.rightKey);
keybindDisabler.addDisabledKey(mc.options.backKey);
keybindDisabler.addDisabledKey(mc.options.inventoryKey);
keybindDisabler.addDisabledKey(mc.options.chatKey);
keybindDisabler.addDisabledKey(mc.options.playerListKey);
keybindDisabler.addDisabledKey(mc.options.jumpKey);
}
if (client.options != null) {
previousViewBob = client.options.getBobView().getValue();
client.options.getBobView().setValue(false);
client.options.hudHidden = true;
}
}
private void handlePause() {
if (!started) {
this.startTime = System.currentTimeMillis();
this.started = true;
showBlackScreen(60, true);
}
float timer = (float) (System.currentTimeMillis() - startTime) / PAUSE_DURATION;
if (client.options != null) {
client.options.hudHidden = true;
}
if (timer >= 1.0f) {
this.falling = true;
this.startTime = System.currentTimeMillis();
}
}
private void handleFall() {
float timer = (float) (System.currentTimeMillis() - startTime) / FALL_DURATION;
if (timer >= 1.0f) {
showBlackScreen(50, true);
this.ending = true;
this.falling = false;
this.startTime = System.currentTimeMillis() + 2500L;
if (client.player != null) {
CameraModifier cameraModifier = EffectManager.getEffect(CameraModifier.class);
if (cameraModifier != null) {
cameraModifier.set(ix,
iy,
iz,
15, 90);
}
}
} else {
if (client.options != null) {
client.options.hudHidden = true;
}
Vec3d newPos = interpolateFallPosition(timer);
Vec3d newRot = interpolateFallRotation(timer);
this.cameraRoll = (float) newRot.z;
CameraModifier cameraModifier = EffectManager.getEffect(CameraModifier.class);
if (cameraModifier != null) {
cameraModifier.set(newPos.x, newPos.y, newPos.z,
(float) newRot.y, (float) newRot.x, cameraRoll);
}
}
}
private void handleEnding() {
float timer = (float) (System.currentTimeMillis() - startTime) / END_DURATION;
if (timer >= 1.0f) {
showBlackScreen(40, true);
stopCutscene();
} else {
if (client.options != null) {
client.options.hudHidden = true;
}
if (client.player != null) {
cameraRoll = 100;
CameraModifier cameraModifier = EffectManager.getEffect(CameraModifier.class);
if (cameraModifier != null) {
cameraModifier.set(ix,
iy + 0.2,
iz,
-180, 0, cameraRoll);
}
}
}
}
private Vec3d interpolateFallPosition(float timer) {
float easedTimer = easeInSine(timer);
double startY = iy + 193;
double y = MathHelper.lerp(easedTimer, startY, iy);
return new Vec3d(ix, y, iz);
}
private Vec3d interpolateFallRotation(float timer) {
float pitch, yaw, roll;
if (timer < 0.5f) {
float t = timer * 2.0f;
float eased = easeInOutSine(t);
pitch = MathHelper.lerp(eased, 80, 60);
roll = MathHelper.lerp(eased, 20, -20);
} else {
float t = (timer - 0.5f) * 2.0f;
float eased = easeInOutSine(t);
pitch = MathHelper.lerp(eased, 60, 110);
roll = MathHelper.lerp(eased, -20, 0);
}
yaw = MathHelper.lerp(timer, 0, 120);
return new Vec3d(pitch, yaw, roll);
}
private float easeInSine(float t) {
return 1 - (float) Math.cos((t * Math.PI) / 2);
}
private float easeInOutSine(float t) {
return -(float) (Math.cos(Math.PI * t) - 1) / 2;
}
private void showBlackScreen(int durationTicks, boolean pauseSounds) {
this.blackScreenDuration = durationTicks * 50L;
this.blackScreen = true;
this.blackScreenStartTime = System.currentTimeMillis();
this.shouldPauseSounds = pauseSounds;
if (client.options != null) {
client.options.hudHidden = true;
}
}
private void tickBlackScreen() {
if (blackScreen) {
float timer = (float) (System.currentTimeMillis() - blackScreenStartTime) / blackScreenDuration;
if (timer >= 1.0f) {
this.blackScreen = false;
if (client.options != null) {
client.options.hudHidden = false;
client.options.getBobView().setValue(previousViewBob);
}
if (client.getSoundManager() != null) {
client.getSoundManager().resumeAll();
}
} else {
if (shouldPauseSounds && client.getSoundManager() != null) {
client.getSoundManager().pauseAll();
}
if (client.options != null) {
client.options.hudHidden = true;
}
}
}
}
private void stopCutscene() {
setActive(false);
this.hasInitializedLocation = false;
this.started = false;
this.falling = false;
this.ending = false;
this.blackScreen = false;
this.cameraRoll = 0;
if (client.player != null) {
client.cameraEntity = client.player;
}
if (client.options != null) {
client.options.hudHidden = false;
client.options.getBobView().setValue(previousViewBob);
}
CameraModifier cameraModifier = EffectManager.getEffect(CameraModifier.class);
if (cameraModifier != null) cameraModifier.setActive(false);
KeybindDisabler keybindDisabler = EffectManager.getEffect(KeybindDisabler.class);
if (keybindDisabler != null) {
keybindDisabler.clearDisabledKeys();
keybindDisabler.setActive(false);
}
if (client.getSoundManager() != null) {
client.getSoundManager().resumeAll();
}
this.startTime = 0L;
}
@Override
public void reset() {
stopCutscene();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment