Summary
Encore Hall is a shared virtual recording studio in MUD Foundation. Visitors walk through four genre rooms (Rock, Hip-Hop, Electronic, Country), like their favorite artists, and watch the community's top four fill each room's All-Time Four frames. The space is never finished: it looks different after every visit, because the visitors decide who is on the wall. Enter the space.
The Rooms
A studio hub with four colored corridors. Each corridor matches the color of the room it leads to, and that is the wayfinding. Tap a room:
Rock
- Concert stage at the back with amps and a drum kit
- Bar and a lounge up front, plus a clickable jukebox
- "Sold Out Tonight" signs set the scene
Hip-Hop
- A walkable DJ riser in the middle of the room
- Record shop along one wall
- Block-party signs and graffiti
Electronic
- Checkered dance floor with lasers
- A walkable riser stage, a bar and a lounge
- Arcade cabinets in the corners
Country
- Corner stage you can walk onto
- Saloon bar with a mirror and longhorn
- Hay bales, string lights and a jukebox
Features
Like and unlike
Click an artist, click again to undo. The top four per room move into the All-Time Four frames, and votes are stored permanently so the wall changes between visits.
Live boards
Each room lists all 20 artists with live like counts, and the hub board shows each room's current leader.
Encore button
Confetti and a light show for everyone in the room at once.
Lounges
Sofas and bars in every room. Visitors talk over voice or text chat while they argue about rankings.
Audio zones
Music changes as you walk between rooms, mixed low so voice chat stays clear.
Golden Record hunt
One hidden record per room. Find all four to unlock a spinning gold trophy and confetti in the hub.
Design Choices
Spatial design
- Hub-and-spoke layout: one hub, four corridors, four rooms, so nobody gets lost.
- Each room has its own palette, layout and set pieces (rock stage, hip-hop DJ riser, electronic dance floor, country saloon).
- Walls are solid and the stages are walkable, so the rooms feel like places.
Interaction
- One click to like, one click to undo, with a pop-up that confirms what you did.
- Empty frames say "Vote to fill this spot," so the goal is clear before you read anything.
- Encore and the like boards are shared, so what you do changes the room for everyone in it.
User experience
- A How To Play sign in the hub covers walking, looking, liking and the Encore button.
- Large, high-contrast signs, plus a "Back to the Studio" sign in every room.
- Music is mixed quiet so voice chat is never drowned out.
Limits
- Likes are once per artist per visit, since the platform has no per-person identity.
- Five of the 80 portraits are placeholder cards.
- Visitors use MUD's own avatar menu; custom avatars are not possible from the script.
Media
Click any image to enlarge it.








Code
The whole world is one JavaScript file running inside the MUD XR Creator. These three pieces are the heart of it (trimmed for readability). The shared MUD store is what makes it multiplayer: every visitor reads and writes the same counters. View the full script on GitHub.
1. Like and unlike
Every like is one shared counter in the MUD store. Clicking again undoes it, and the Liked time is saved so ties are broken fairly.
async function like(b) {
const a = b.a;
if (pend[a.key]) return; // ignore double-clicks while saving
pend[a.key] = true;
if (LIKED[a.key]) { // already liked -> unlike
LIKED[a.key] = 0;
await store.inc(a.key, -1);
showToast("UNLIKED: " + a.name, 2);
} else { // like
LIKED[a.key] = 1;
await store.inc(a.key, 1);
await store.set("t:" + a.key, Date.now()); // timestamp for tie-breaks
showToast("LIKED: " + a.name, 2);
}
pend[a.key] = false;
await refresh(); // re-read the store and re-rank the room
}2. The All-Time Four
Reads everyone's likes from the store, sorts each room's 20 artists, and puts the top four into the portrait frames.
function rank(r, d) { // d = the whole shared store
ART[r.k].forEach((a) => {
a.n = d[a.key] || 0; // like count
a.t = d["t:" + a.key] || 0; // time of latest like
});
const top = ART[r.k]
.filter((a) => a.n > 0)
.sort((a, b) => b.n - a.n || a.t - b.t || (a.name < b.name ? -1 : 1))
.slice(0, 4); // most likes first, earliest like wins ties
slots[r.k].forEach((slot, i) => show(r, slot, top[i], i)); // fill the 4 frames
}3. Shared Encore button
Pressing the pad bumps a counter in the store. Everyone in the room checks that counter every 1.5 seconds, and when it goes up they all see the confetti.
async function encore(pad) {
playEncore(pad); // my own confetti right away
encSeen[pad.r.k] = await store.inc("enc:" + pad.r.k, 1);
}
// in the update loop, every 1.5 seconds:
const room = zoneAt(cpos.x, cpos.z); // which room am I standing in?
const count = await store.get("enc:" + room, 0);
if (count > encSeen[room]) playEncore(pad); // someone else pressed it
encSeen[room] = count;