Skip to content
Merged
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
10 changes: 0 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@ FetchContent_Declare(
)
FetchContent_MakeAvailable(glm)

# FastNoise
FetchContent_Declare(
fastnoise
GIT_REPOSITORY https://github.com/Auburn/FastNoiseLite.git
GIT_TAG master
)
FetchContent_MakeAvailable(fastnoise)

# stb_image
FetchContent_Declare(
stb
Expand Down Expand Up @@ -268,7 +260,6 @@ target_include_directories(ft_minecraft PRIVATE
${CMAKE_SOURCE_DIR}/include/shared/Mobs
${CMAKE_SOURCE_DIR}/include/shared/Inventories
${glm_SOURCE_DIR}
${fastnoise_SOURCE_DIR}/Cpp
${glad_SOURCE_DIR}/include
${stb_SOURCE_DIR}
${zstd_SOURCE_DIR}/lib
Expand Down Expand Up @@ -302,7 +293,6 @@ target_include_directories(ft_minecraft_server PRIVATE
${CMAKE_SOURCE_DIR}/include/shared/Mobs
${CMAKE_SOURCE_DIR}/include/shared/Inventories
${glm_SOURCE_DIR}
${fastnoise_SOURCE_DIR}/Cpp
${zstd_SOURCE_DIR}/lib
)
# Should look into restructure stuff so we can remove glad from server
Expand Down
33 changes: 33 additions & 0 deletions COPYRIGHT
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
ft_minecraft — Pimp My World
Copyright (C) 2026 Leonard Skraber <lskraber@student.42lausanne.ch>
Copyright (C) 2026 Lucas Dominique <ldominiq@student.42lausanne.ch>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.

----------------------------------------------------------------------

Note on bundled assets:

The source code of ft_minecraft is licensed under the GNU AGPLv3 (see LICENSE).
The assets shipped under assets/ are NOT covered by the AGPLv3 and remain
the property of their respective authors. They are used here for
non-commercial, educational purposes within the scope of the 42 school
project. See the "Credits & Assets" section of README.md for details:

- Music: patrickdearteaga.com
- SFX: Mojang Studios (Minecraft)
- Textures: 16x C-Tetra, Alternate Ingots, Minetest Game default textures

Anyone redistributing this project should review the licensing terms of
each asset source before bundling them.
661 changes: 661 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

13 changes: 0 additions & 13 deletions README

This file was deleted.

273 changes: 273 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
<div align="center">

<img src="assets/textures/FT-MINECRAFT.png" alt="ft_minecraft" width="420"/>

# ft_minecraft

### *Pimp My World* - a voxel sandbox written from scratch in C++ & OpenGL

[![C++20](https://img.shields.io/badge/C%2B%2B-20-00599C?logo=c%2B%2B&logoColor=white)](https://en.cppreference.com/w/cpp/20)
[![OpenGL](https://img.shields.io/badge/OpenGL-4.6-5586A4?logo=opengl&logoColor=white)](https://www.opengl.org/)
[![CMake](https://img.shields.io/badge/CMake-3.22%2B-064F8C?logo=cmake&logoColor=white)](https://cmake.org/)
[![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20Windows-lightgrey)]()
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](LICENSE)

</div>

---

## ✨ Overview

**ft_minecraft** is a from-scratch voxel engine inspired by Minecraft, built as the
follow-up to the *ft_vox* project at 42. The emphasis is on **procedural generation**
and **rendering quality** - building a world that looks good, runs smoothly, and is
fun to explore alone or with friends over the network.

Everything from terrain generation to lighting, shadows and chunk meshing is implemented
by hand. Only thin third-party libraries are used (windowing, image loading, audio
playback, fonts, math).

## 🚀 Features

### 🌍 Procedural world
- **16 biomes** with smooth transitions: Plains, Desert, Red Desert, Dark Forest,
Birch Forest, Jungle, Savanna, Mesa, Mountain, Tundra, Ice Plains, Swamp,
Ocean, Mushroom Island, Volcanic, Nether.
- Per-biome geography, elevation, vegetation and color palette.
- Procedurally-generated trees with varying shape, height, width and leaf density.
- Small plants, flowers, tall grass and mushrooms scattered throughout the world.
- Lakes and **meandering rivers** carved across the surface.
- **Realistic water simulation** - dynamic flow and spreading: place a
water source and the liquid propagates, fills depressions and pours off ledges
in real time.
- **Worm-style cave systems** with natural cave entrances, and **clustered ores**
(coal, iron, gold, diamond…).
- **Persistent chunks**: blocks you break or place stay broken/placed across
unload/reload, and are synchronized in multiplayer.
- Chunks are generated and meshed **on demand** as the player moves - only the
chunks within view get built, and they're released again when far enough away,
so the world is effectively infinite without baking it all up-front.
- Navigable over the 5,000,000-block XZ requirement.

### 🎨 Rendering
- Custom OpenGL 4.6 renderer with a deferred-style **G-Buffer**.
- **Directional sun lighting** with **Cascaded Shadow Maps** (CSM) and alpha-tested
shadow casters for leaves/vegetation.
- **Screen-Space Ambient Occlusion** (SSAO) with blur pass.
- **Volumetric 3D clouds** rendered via a dedicated shader and composited.
- **Procedural sky** with a precomputed **Sky LUT** (atmospheric scattering style).
- **Transparent water** with reflection/refraction framebuffers, DuDv normal-mapped
waves and underwater caustics.
- **Underwater post-effect**: color tint and reduced visibility when the camera
is submerged.
- **Far-distance fog** for immersion.
- **Auto-exposure** (luminance reduction) for HDR-like tone mapping.
- **Bit-packed vertex format** for a lean GPU footprint, plus view-frustum culling.

### 🎮 Gameplay
- First-person camera, mouse look (full 360° Y axis), WASD movement, jump, sprint,
sneak, and a **fly / spectator mode** (×20 speed).
- **Gravity & block collisions**, swimming/diving in water with optional slowed
movement.
- **Break / place blocks** with raycasting; picked-up blocks go into the inventory.
- **Hotbar + full inventory UI** with drag-and-drop, stacking and a hand slot.
- **Crafting system** with crafting station / recipes.
- **Item entities** (block drops) you can pick up.
- **Hostile mobs**: zombies and creepers that spawn around the player and chase
on approach, with their own animations and skins.
- Basic walking and attacking animations for the player.

### 🔊 Audio (SoLoud)
- Per-biome **ambient music** with smooth cross-fades between biomes.
- Player & mob sounds: footsteps (per-material), attacking, swimming, block
break/place, liquid SFX.
- Distance-attenuated, stereo positional audio.
- In-game **sound menu** to balance master / music / SFX volumes.

### 🌐 Multiplayer
- Custom **UDP client/server** (`ft_minecraft` ↔ `ft_minecraft_server`).
- World is **generated on the server** and streamed to clients on demand
(with zstd compression for chunk payloads).
- 4+ players supported, with synchronized:
- block placement / destruction (persistent on the server),
- mob spawns and entity states,
- player positions, animations and actions.
- In-game **chat** and **player list** HUD.

### 🖥️ Interface
- Main menu, pause menu, multiplayer menu, settings menu (controls / graphics /
sounds) - all rendered with FreeType + a custom GUI renderer.
- **Debug HUD** (toggleable): FPS, triangle count, cube count, chunk count,
player position, biome, etc.
- Chunk-boundary debug overlay and a wireframe / hitbox renderer.
- Configurable controls and graphics settings (render distance, etc.).
- **Dev tweaks panel** (Dear ImGui).

## 📸 Screenshots

<div align="center">

| | |
|:-:|:-:|
| ![Biomes transition](assets/screenshots/biomes.png) | ![Trees & vegetation](assets/screenshots/vegetation.png) |
| *Smooth biome transitions* | *Procedurally generated trees* |
| ![Rivers & lakes](assets/screenshots/water.png) | ![Caves & ores](assets/screenshots/caves.png) |
| *Rivers, lakes and transparent water* | *Cave systems with ore clusters* |
| ![Shadows & SSAO](assets/screenshots/lighting.png) | ![Sky & clouds](assets/screenshots/sky.png) |
| *Directional lighting, shadows, SSAO* | *Volumetric clouds and procedural sky* |
| ![Multiplayer](assets/screenshots/multiplayer.png) | ![Inventory & crafting](assets/screenshots/inventory.png) |
| *Multiplayer session* | *Inventory and crafting UI* |

</div>

## 🛠️ Build & Run

### Dependencies

The project uses CMake `FetchContent` to pull most dependencies automatically
(GLFW, GLAD, GLM, stb, ImGui, zstd, FreeType, SoLoud). You only
need a recent toolchain and the system libraries GLFW needs for Wayland/X11:

```bash
# Ubuntu / Debian
sudo apt install build-essential cmake git \
libwayland-dev libxkbcommon-dev xorg-dev
```

> Requires a C++20 compiler and an OpenGL **4.6**-capable GPU.

### Build

A one-liner is provided:

```bash
./build.sh
```

Or the manual equivalent:

```bash
mkdir -p build && cd build
cmake ..
make -j$(nproc)
```

This produces two executables in `build/`:

| Binary | Role |
|---|---|
| `ft_minecraft` | Game client (window, rendering, input) |
| `ft_minecraft_server` | Standalone dedicated server |

### Run

**Singleplayer / connect to a local server:**

```bash
# Terminal 1 - start the server (optional seed)
./ft_minecraft_server [seed]

# Terminal 2 - start the client
./ft_minecraft
```

The client can also connect to a remote server through the multiplayer menu.

## 🎮 Default controls

| Action | Key |
|---|---|
| Move | `W` `A` `S` `D` |
| Jump / fly up | `Space` |
| Sneak / fly down | `Left Shift` |
| Sprint | `Left Ctrl` |
| Drop item | `Q` |
| Hotbar slot | `1` – `9` |
| Inventory | `E` |
| Chat / commands | `T` / `Enter` |
| Hide HUD | `F2` |
| Debug HUD | `F3` |
| Dev ImGui overlay | `F6` |
| Pause / menu | `Esc` |

Most keys are rebindable from the in-game **Settings → Controls** menu.
**Fly mode** can be toggled from the ImGui dev overlay (`F6`), from the
in-game settings tab, or with the chat command `/gamemode spectator`.

## 📂 Project layout

```
ft_minecraft/
├── assets/ # textures, sounds, skins, videos
├── fonts/ # TTF fonts used by the GUI
├── shaders/ # all GLSL shaders (sky, water, SSAO, CSM, clouds, …)
├── include/
│ ├── client/ # renderer, menus, characters, items, audio
│ ├── server/ # world, chunk generation, server loop
│ └── shared/ # protocol, chunk format, entities, mobs, inventories
├── src/
│ ├── client/ # OpenGL client implementation
│ ├── server/ # dedicated server implementation
│ └── shared/ # code shared between client and server
├── CMakeLists.txt
├── build.sh
└── en.subject.pdf # 42 subject (Pimp My World)
```

## 🧱 Tech stack

| Area | Library / tech |
|---|---|
| Language | C++20 |
| Build | CMake 3.22 + FetchContent |
| Windowing / input | GLFW |
| GPU API | OpenGL 4.6 (via GLAD) |
| Math | GLM |
| Image loading | stb_image |
| Dev tools | Dear ImGui (runtime tweaks) |
| Menus / text | FreeType + custom GUI renderer |
| Audio | SoLoud (MiniAudio backend) |
| Compression | zstd (chunk payloads) |
| Networking | Raw UDP sockets (BSD / Winsock) |

## 🙏 Credits & Assets

This project bundles third-party assets - all credit to their original authors.

**Music**
- [patrickdearteaga.com](https://patrickdearteaga.com) - biome ambient tracks.

**Sound effects**
- Mojang Studios (Minecraft SFX).

**Texture packs**
- [16x C-Tetra (1.13)](https://www.planetminecraft.com/texture-pack/16x-c-tetra-1-13/) - Textures.
- [Alternate Ingots](https://modrinth.com/resourcepack/alternate-ingots?version=1.20) - Ingots.
- [Minetest Game - `default` textures](https://github.com/luanti-org/minetest_game/tree/master/mods/default/textures) - Tools & more.

All assets remain the property of their respective authors and are used here
for non-commercial, educational purposes within the scope of the 42 school
project.

## 📜 License

The **source code** of ft_minecraft is licensed under the
**GNU Affero General Public License v3.0** — see [LICENSE](LICENSE) and
[COPYRIGHT](COPYRIGHT).

> In short: you may use, study, modify and redistribute this code, including
> over a network, **provided that** any modified version you distribute (or
> make available to users over a network) is also released under the AGPLv3
> with its full source code.

The **bundled assets** in `assets/` (music, sound effects, textures) are
**not** covered by the AGPLv3 — they remain the property of their respective
authors and are used here under their own terms for non-commercial,
educational purposes (see [Credits & Assets](#-credits--assets)).

## 👥 Authors

- **Leonard Skraber** - `lskraber@student.42lausanne.ch`
- **Lucas Dominique** - `ldominiq@student.42lausanne.ch`

> 42 Lausanne
Binary file added assets/screenshots/biomes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/screenshots/caves.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/screenshots/inventory.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/screenshots/lighting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/screenshots/multiplayer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/screenshots/sky.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/screenshots/vegetation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/screenshots/water.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 0 additions & 7 deletions doc

This file was deleted.

8 changes: 4 additions & 4 deletions include/client/AudioManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class AudioManager {
void shutdown();

// Per-frame: drives 3D listener, biome music crossfade, footsteps, mob audio.
// `isPlaying` mirrors App::GameState::Playing false suspends music + mutes triggers.
// `isPlaying` mirrors App::GameState::Playing - false suspends music + mutes triggers.
void update(float deltaTime, bool isPlaying, Camera& cam, Renderer& world);

// Switch ambient music. Crossfades over ~3s
Expand Down Expand Up @@ -170,7 +170,7 @@ class AudioManager {
// ---- listener-jump detection ------------------------------------------
// Player respawn / debug teleport moves the listener in a single frame. Active 3D voices
// (especially long ones like the creeper fuse) keep playing at their absolute world coords,
// and SoLoud's spatializer recomputes their pan/volume against the new listener the
// and SoLoud's spatializer recomputes their pan/volume against the new listener - the
// result is an audible click/glitch on the next buffer. Tracking the listener position
// lets us detect that jump and stop the long-running 3D voices we own.
glm::dvec3 prevListenerPos{0.0};
Expand All @@ -197,7 +197,7 @@ class AudioManager {
glm::dvec3 lastPos{}; // last seen position, used for 3D death/explode sfx
// Position of the most recently consumed snapshot. We compute footstep deltas from THIS,
// not from snapshots[size-2], because Renderer.cpp wipes & reseeds the snapshots vector
// whenever there's a >100ms server-side gap losing the first move-after-idle every
// whenever there's a >100ms server-side gap - losing the first move-after-idle every
// stop/go cycle (chase→attack→chase). Caching it here survives the reseed.
glm::dvec3 lastConsumedPos{};
bool hasLastConsumedPos = false;
Expand All @@ -216,7 +216,7 @@ class AudioManager {
// prevPrimed before, which mis-fired when a primed creeper got killed mid-fuse).
bool diedByExplosion = false;
// SoLoud voice for the active creeper fuse one-shot. Tracked so we can stop it on
// unprime / death / explode otherwise the sample keeps playing at the creeper's old
// unprime / death / explode - otherwise the sample keeps playing at the creeper's old
// position and glitches when the listener jumps (player death + respawn far away).
SoLoud::handle fuseHandle = 0;
// Set when the packet handler fires a death sfx; sweep skips it to avoid double-firing.
Expand Down
Loading
Loading