Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# PixelReel Custom Fork Changelog

## v1.1.0

Screenwriter media-server load controls.

- Screenwriter now starts **OFF by default** in fresh worlds. Existing worlds keep their saved ON/OFF state.
- Added `/screenwriter maxstreams <0-30>` to cap the number of **simultaneous scheduled auditorium shows**.
- Default simultaneous-show limit is **4**. A value of `0` means unlimited.
- Daily schedule generation now respects that cap for the complete duration of every movie, not just the start time.
- Scheduling is built chronologically across all linked auditoriums so higher auditorium numbers still receive shows as capacity becomes available.
- Changing the limit preserves the already-generated day; `/screenwriter regenerate` applies the new setting to today's schedule.
- `/screenwriter status` now reports the configured simultaneous-show limit.

## v1.0.0

First formal release of the theater-focused PixelReel Custom Fork.

### Custom cinema screens

- Replaced the normal screen lineup with two user-facing theater screens:
- **Custom Cinema Screen** — flat.
- **Custom Curved Cinema Screen** — dynamically curved using the original PixelReel curved-screen profile.
- Both screens open a placement menu for custom width, height, audio depth, and side range.
- Supported custom dimensions: **1–64 blocks wide** and **1–36 blocks tall**.
- Default custom dimensions: **27 × 11**.
- Screen placement validates that all required panel cells are available before consuming the item.
- Custom screen geometry, size, and audio-zone settings persist in the block entity and sync to clients.
- Flat screens render/collide against the back face of their occupied cells so they can sit flush against a wall.
- Breaking any generated screen panel removes the complete bound display. Survival drops the controller item normally; creative does not duplicate it.
- Legacy preset display registrations remain internally for world compatibility, but the old preset TV/monitor items are no longer part of the normal creative/crafting lineup.

### Auditorium audio

- Custom screens use a hard auditorium-shaped audio zone rather than circular distance attenuation.
- Default audio zone: **40 blocks forward**, **2 blocks beyond each screen edge**, and **1 block behind the screen**.
- Audio remains at the screen's configured volume anywhere inside the zone and becomes silent outside it.
- The client chooses at most one audible screen when zones overlap.
- Replaced shared LibVLC native volume output with per-screen decoded PCM callbacks and independent JavaSound output.
- Each physical screen has its own playback/audio session, preventing simultaneous auditorium tracks from mixing.

### Remote Control

- Added a Remote Control that can target screens from a longer distance and open normal screen controls.
- Added **Reset Connection** to rebuild only the local client's media/audio session for the selected screen and reconnect at the current synchronized playback position.
- The remote is also used to link custom cinema screens to Screenwriter.
- Recipe:

```text
II
RB
II
```

- `I` = Iron Ingot
- `R` = Redstone
- `B` = any Button

### Screenwriter theater automation

- Added the **Screenwriter Console** for centralized real-world theater scheduling.
- Supports up to **30 linked custom cinema screens**.
- Auditorium numbers are user-selected and unique from **1–30**; link order does not determine auditorium number.
- Re-linking can change an auditorium number without deleting that auditorium's current generated schedule.
- Right-click the console to arm linking; sneak + right-click a custom screen with the Remote Control to open the auditorium link/update menu.
- Shift + right-click the console toggles Screenwriter on/off.
- Screenwriter can also be enabled/disabled through commands.
- Generates a new schedule for the current real-world day from configured **Jellyfin or Plex** movie libraries.
- Provider mode can be `AUTO`, `JELLYFIN`, or `PLEX`; AUTO prefers Jellyfin when available and otherwise uses Plex.
- Only movies with runtime metadata are scheduled.
- Uses runtime metadata to calculate exact end times.
- Supports configurable theater opening/closing times, turnaround gaps, and first-show staggering.
- Default settings:
- open: **11:00 AM**
- close: **11:30 PM**
- turnaround: **20 minutes**
- first-show stagger window: **30 minutes**
- later-show rounding: **10 minutes**
- The first show in each auditorium is distributed through the stagger window rather than starting every auditorium at opening time.
- A movie used in the previous **3 calendar days** is excluded from the current day's random schedule.
- A movie is used at most once in the same generated day.
- Schedules are saved to `pixelreel-screenwriter.json` in the world folder and are not rerolled by server restarts.
- If the server starts during an active scheduled movie, Screenwriter resumes that movie at the elapsed real-world position.
- Screenwriter powers linked displays off between shows.
- Turning Screenwriter off stops its controlled playback and prevents automatic generation until re-enabled.

### Screenwriter commands

```text
/screenwriter
/screenwriter status
/screenwriter on
/screenwriter off
/screenwriter schedule
/screenwriter book
/screenwriter generate
/screenwriter regenerate
/screenwriter source <auto|jellyfin|plex>
/screenwriter open <time>
/screenwriter close <time>
/screenwriter turnaround <minutes>
/screenwriter stagger <minutes>
```

Opening/closing times accept compact 24-hour input such as `930`, `1100`, `1830`, and `2330`; colon-formatted input is also accepted internally.

### Schedule book and chat output

- `/screenwriter schedule` prints the complete current schedule in chat.
- `/screenwriter book` gives the player a written book titled **Today's Movie Schedule**.
- Book pages wrap long movie titles and automatically continue an auditorium onto additional pages rather than cutting off shows.

### Screenwriter Console recipe and texture

Recipe:

```text
III
IRI
DDD
```

- `I` = Iron Ingot
- `R` = Redstone
- `D` = Polished Deepslate

The Screenwriter Console uses a custom pixel-art theater scheduling/control texture.

### Compatibility and release identity

- Display name: **PixelReel Custom Fork**.
- Release version: **1.1.0**.
- Build artifact: `pixelreel-custom-fork-1.1.0.jar`.
- Internal Fabric mod id intentionally remains `pixelreel` to preserve existing registry IDs and world compatibility.
- Target: Minecraft `26.3-snapshot-5`, Fabric Loader `>=0.19.3`, Java 25+.
- VLC/libVLC remains required on clients for playback.
30 changes: 22 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
# pixelReel
# PixelReel Custom Fork

Fabric mod for **Minecraft Java Edition 26.3-snapshot-5** that lets you place televisions and cinema screens in your world and watch **live TV** and **on-demand media** together with friends.

Live channels come from a Tunarr (or any M3U + XMLTV) playlist. Movies and shows can come from **Jellyfin**, **Emby**, or **Plex**. Each display keeps its own channel or title, multiple screens can play at once, and audio is positional.


## Custom Fork v1.1.0

This is **PixelReel Custom Fork v1.1.0**, a theater-focused fork of PixelReel for Minecraft Java Edition `26.3-snapshot-5`. The internal mod id remains `pixelreel` so existing worlds keep their registered blocks/items. The build artifact is `pixelreel-custom-fork-1.1.0.jar`.

Version 1 adds:

- configurable **Custom Cinema Screen** and **Custom Curved Cinema Screen** sizes;
- flush wall mounting and whole-screen removal from any panel;
- independent auditorium-shaped audio with true per-screen PCM output;
- a long-range **Remote Control** with connection reset and Screenwriter linking;
- **Screenwriter**, a central theater automation console for up to 30 auditoriums;
- Screenwriter starts **OFF by default** in fresh worlds and defaults to a **4-show simultaneous scheduling cap** to reduce media-server load;
- automatic daily Jellyfin/Plex movie schedules with runtimes, turnaround time, opening/closing hours, first-show staggering, a three-day no-repeat rule, and configurable simultaneous-show limiting;
- persistent schedules, restart/resume synchronization, chat schedules, and written schedule books.

See `CHANGELOG.md` for the v1 feature list and `GITHUB_PULL_REQUEST_DESCRIPTION.md` for a detailed implementation overview.

## Requirements


Expand Down Expand Up @@ -41,7 +59,7 @@ gradlew.bat clean build
The installable JAR is:

```text
build\libs\pixelreel-1.0.0.jar
build\libs\pixelreel-custom-fork-1.1.0.jar
```

Use the JAR **without** `-sources`.
Expand All @@ -56,7 +74,7 @@ run-client.bat

1. Install Fabric Loader for Minecraft **26.3-snapshot-5**.
2. Put **Fabric API** in your `mods` folder.
3. Put `pixelreel-1.0.0.jar` in `mods`.
3. Put `pixelreel-custom-fork-1.1.0.jar` in `mods`.
4. Install **64-bit VLC** on every client that should see video.

The mod runs on clients and servers (`environment: *`). For multiplayer, **both sides** need the mod. VLC is only required on clients.
Expand Down Expand Up @@ -218,7 +236,6 @@ What already works in this snapshot build — crossed out as complete:
- [x] ~~Subtitles, letterboxing, and HDR tone mapping~~
- [x] ~~Pixel Glasses fullscreen overlay~~
- [x] ~~Craftable displays + creative tab~~
- [x] Fabric mod targeting Minecraft **1.21.1**

### Upcoming

Expand All @@ -229,13 +246,10 @@ What already works in this snapshot build — crossed out as complete:
| **Movie scheduler** | Planned | Medium | Queue showtimes (date/time + title or channel). Auto power-on, start playback, and optional lobby announcements for cinema nights. |
| **YouTube / streaming integration** | Planned | Medium | Play YouTube (and possibly other stream sources) on displays alongside Tunarr and media servers. Exact providers TBD. |
| **Posters as paintings** | Planned | Medium | Place movie/show posters in the world as painting-style decor (from library artwork), not only inside the browse menus. |
| **Fabric on stable versions** | Planned | High | Port from `26.3-snapshot-5` to older/stable Fabric target **1.20.1**. |
| **Fabric on stable versions** | Planned | High | Port from `26.3-snapshot-5` to older/stable Fabric targets such as **1.21.1** and **1.20.1**. |
| **NeoForge support** | Planned | High | First-class NeoForge build so servers/clients on NeoForge can run pixelReel. |
| **Forge support** | Planned | Medium | Forge port after (or alongside) NeoForge, depending on version demand. |

DISCORD: https://discord.gg/RSWQuEnMj
Mincraft Mod 1.21.1: https://github.com/Samarth-programming/PixelReel_1.21.1

Ideas and PRs welcome — especially for loaders, version ports, and the admin remote.


2 changes: 1 addition & 1 deletion build-mod.bat
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@echo off
rem Builds the pixelReel mod JAR into build\libs\
rem Builds the PixelReel Custom Fork JAR into build\libs\
setlocal
cd /d "%~dp0"
call gradlew.bat clean build
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ loader_version=0.19.3
loom_version=1.17-SNAPSHOT

# Mod Properties
mod_version=1.0.0
mod_version=1.1.0
maven_group=com.pixelreel

# Dependencies
Expand Down
2 changes: 1 addition & 1 deletion run-client.bat
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@echo off
rem Launches a Minecraft 26.3-snapshot-5 development client with the pixelReel mod.
rem Launches a Minecraft 26.3-snapshot-5 development client with the PixelReel Custom Fork.
rem Requires 64-bit VLC to be installed for video playback (https://www.videolan.org).
setlocal
cd /d "%~dp0"
Expand Down
2 changes: 1 addition & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ pluginManagement {
}

// Should match your modid
rootProject.name = 'pixelreel'
rootProject.name = 'pixelreel-custom-fork'
29 changes: 29 additions & 0 deletions src/client/java/com/pixelreel/client/ClientNetworking.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;

public final class ClientNetworking {
private static OnDemandProvider pendingBrowseProvider = OnDemandProvider.JELLYFIN;
Expand Down Expand Up @@ -258,6 +259,34 @@ public static void unequipPixelGlasses() {
}
}

public static void placeCustomScreen(
BlockPos pos, int width, int height, int audioDepth, int audioSide, InteractionHand hand
) {
if (ClientPlayNetworking.canSend(ModNetworkPayloads.PlaceCustomScreen.TYPE)) {
ClientPlayNetworking.send(new ModNetworkPayloads.PlaceCustomScreen(
pos, width, height, ModNetworkPayloads.PlaceCustomScreen.packAudioSettings(audioDepth, audioSide),
hand == InteractionHand.OFF_HAND
));
}
}

public static void configureScreenwriterLink(BlockPos pos, int auditorium, boolean unlink) {
if (ClientPlayNetworking.canSend(ModNetworkPayloads.ScreenwriterLink.TYPE)) {
ClientPlayNetworking.send(new ModNetworkPayloads.ScreenwriterLink(pos, auditorium, unlink));
}
}


public static void resetLocalPlaybackConnection(BlockPos pos) {
Minecraft minecraft = Minecraft.getInstance();
boolean reset = PlaybackManager.INSTANCE.resetConnection(pos);
if (minecraft.player != null) {
minecraft.player.sendOverlayMessage(Component.translatable(
reset ? "message.pixelreel.playback.connection_reset" : "message.pixelreel.playback.no_connection"
));
}
}

public static void sendControl(BlockPos pos, ScreenAction action, float value) {
if (ClientPlayNetworking.canSend(ModNetworkPayloads.ScreenControl.TYPE)) {
ClientPlayNetworking.send(new ModNetworkPayloads.ScreenControl(pos, action, value));
Expand Down
15 changes: 15 additions & 0 deletions src/client/java/com/pixelreel/client/PixelReelClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.pixelreel.blockentities.DisplayBlockEntity;
import com.pixelreel.blocks.DisplayBlock;
import com.pixelreel.PixelReel;
import com.pixelreel.client.gui.CustomScreenPlacementScreen;
import com.pixelreel.client.gui.ScreenwriterLinkScreen;
import com.pixelreel.client.playback.PlaybackManager;
import com.pixelreel.client.playback.video.VlcRuntime;
import com.pixelreel.client.render.DisplayBlockEntityRenderer;
Expand All @@ -19,6 +21,7 @@
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;

Expand All @@ -42,6 +45,18 @@ public void openChannelMenu(BlockPos controllerPos) {
public void releasePlayback(BlockPos controllerPos) {
PlaybackManager.INSTANCE.release(controllerPos);
}

@Override
public void openCustomScreenPlacement(BlockPos controllerPos, InteractionHand hand, boolean curved) {
Minecraft minecraft = Minecraft.getInstance();
minecraft.execute(() -> minecraft.gui.setScreen(new CustomScreenPlacementScreen(controllerPos, hand, curved)));
}

@Override
public void openScreenwriterLink(BlockPos controllerPos) {
Minecraft minecraft = Minecraft.getInstance();
minecraft.execute(() -> minecraft.gui.setScreen(new ScreenwriterLinkScreen(controllerPos)));
}
});

ClientTickEvents.END_CLIENT_TICK.register(minecraft -> {
Expand Down
Loading