├── .gitignore ├── Cargo.toml ├── LICENSE.txt ├── README.md ├── README ├── Screenshot0.png ├── Screenshot1.png └── Screenshot2.png ├── Res ├── Blocks │ ├── Air.block │ ├── Cactus.block │ ├── CobbleStone │ ├── DeadShrub.block │ ├── Dirt.block │ ├── Glass.block │ ├── GlassBorderless.block │ ├── Grass.block │ ├── OakBark.block │ ├── OakLeaf.block │ ├── OakPlank.block │ ├── OakSapling.block │ ├── Rose.block │ ├── Sand.block │ ├── Stone.block │ ├── TallGrass.block │ └── Water.block ├── Fonts │ └── rs.ttf ├── Textures │ ├── DefaultPack.png │ ├── DefaultPack2.png │ ├── back.png │ ├── bottom.png │ ├── bottomsb.png │ ├── ch.png │ ├── db.png │ ├── dm.png │ ├── dt.png │ ├── front.png │ ├── left.png │ ├── middlesb.png │ ├── right.png │ ├── test.png │ ├── top.png │ └── topsb.png └── info.txt ├── Shaders ├── Basic.frag ├── Basic.vert ├── Chunk.frag ├── Chunk.vert ├── Flora.vert ├── Skybox.frag ├── Skybox.vert └── Water.vert └── src ├── application.rs ├── camera.rs ├── config.rs ├── context.rs ├── entity.rs ├── gl ├── gl_functions.rs └── mod.rs ├── input ├── keyboard.rs ├── mod.rs └── toggle_key.rs ├── item ├── item_stack.rs ├── material.rs └── mod.rs ├── main.rs ├── maths ├── frustum.rs ├── general_maths.rs ├── matrix.rs ├── mod.rs ├── noise_generator.rs ├── ray.rs └── vector2xz.rs ├── mesh.rs ├── model.rs ├── physics ├── aabb.rs └── mod.rs ├── player ├── mod.rs └── player.rs ├── renderer ├── chunk_renderer.rs ├── flora_renderer.rs ├── mod.rs ├── render_info.rs ├── render_master.rs ├── skybox_renderer.rs └── water_renderer.rs ├── shaders ├── basic_shader.rs ├── chunk_shader.rs ├── flora_shader.rs ├── mod.rs ├── shader.rs ├── shader_loader.rs ├── skybox_shader.rs └── water_shader.rs ├── states ├── mod.rs ├── play_state.rs └── state_base.rs ├── texture ├── basic_texture.rs ├── cube_texture.rs ├── mod.rs └── texture_atlas.rs ├── util ├── array2d.rs ├── file_util.rs ├── fps_counter.rs ├── mod.rs ├── random.rs └── unsafe_cell_wrapper.rs └── world ├── block ├── block_data.rs ├── block_database.rs ├── block_id.rs ├── block_types │ ├── block_type.rs │ └── mod.rs ├── chunk_block.rs └── mod.rs ├── chunk ├── chunk.rs ├── chunk_manager.rs ├── chunk_mesh.rs ├── chunk_mesh_builder.rs ├── chunk_section.rs └── mod.rs ├── event ├── mod.rs ├── player_dig_event.rs └── world_event.rs ├── generation ├── biome │ ├── biome.rs │ ├── desert_biome.rs │ ├── grassland_biome.rs │ ├── light_forest.rs │ ├── mod.rs │ ├── ocean_biome.rs │ └── temperate_forest_biome.rs ├── classic_over_world_generator.rs ├── mod.rs ├── structure │ ├── mod.rs │ ├── structure_builder.rs │ └── tree_generator.rs ├── super_flat_generator.rs └── terrain_generator.rs ├── mod.rs ├── world.rs └── world_constants.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | 16 | # RustRover 17 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 18 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 19 | # and can be added to the global gitignore or merged into this file. For a more nuclear 20 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 21 | #.idea/ 22 | 23 | # quilt files 24 | config.txt 25 | /series 26 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "minecraft-rust" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | gl = "0.14.0" 8 | nalgebra-glm = "0.18.0" 9 | sfml = "0.21.0" 10 | lazy_static = "1.4.0" 11 | rand = "0.9.0-alpha.1" 12 | rand_core = "0.9.0-alpha.1" 13 | rand_pcg = "0.9.0-alpha.1" 14 | gl_loader = "0.1.2" 15 | log = "0.4.21" 16 | env_logger = "0.11.3" 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # minecraft-rust 2 | 3 | Rust rewrite of the game Minecraft as a computer graphics practice for me. 4 | With main reference thanks to [MineCraft-One-Week-Challenge](https://github.com/Hopson97/MineCraft-One-Week-Challenge). 5 | 6 | # Gallery 7 | 8 | ![Screenshot0](README/Screenshot0.png) 9 | 10 | ![Screenshot1](README/Screenshot1.png) 11 | 12 | ![Screenshot2](README/Screenshot2.png) 13 | 14 | # Building instructions 15 | 16 | Just execute `cargo run` as common Rust projects do. 17 | 18 | Specifically, because this project depends on `sfml` crate, you may need to read its 19 | [instructions](https://crates.io/crates/sfml) about how to build this crate. 20 | 21 | # License 22 | 23 | This project is licensed under [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license. 24 | Read [LICENSE.txt](LICENSE.txt) for details. 25 | -------------------------------------------------------------------------------- /README/Screenshot0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/README/Screenshot0.png -------------------------------------------------------------------------------- /README/Screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/README/Screenshot1.png -------------------------------------------------------------------------------- /README/Screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/README/Screenshot2.png -------------------------------------------------------------------------------- /Res/Blocks/Air.block: -------------------------------------------------------------------------------- 1 | Name 2 | Air 3 | 4 | Id 5 | 0 6 | 7 | TexTop 8 | 0 0 9 | 10 | TexSide 11 | 0 0 12 | 13 | TexBottom 14 | 0 0 15 | 16 | Opaque 17 | 0 18 | 19 | MeshType 20 | 0 21 | 22 | ShaderType 23 | 0 24 | 25 | Collidable 26 | 0 27 | -------------------------------------------------------------------------------- /Res/Blocks/Cactus.block: -------------------------------------------------------------------------------- 1 | Name 2 | Cactus 3 | 4 | Id 5 | 8 6 | 7 | TexTop 8 | 9 0 9 | 10 | TexSide 11 | 9 1 12 | 13 | TexBottom 14 | 9 0 15 | 16 | Opaque 17 | 1 18 | 19 | MeshType 20 | 0 21 | 22 | ShaderType 23 | 0 24 | 25 | Collidable 26 | 1 27 | -------------------------------------------------------------------------------- /Res/Blocks/CobbleStone: -------------------------------------------------------------------------------- 1 | Name 2 | OakBark 3 | 4 | Id 5 | 13 6 | 7 | TexAll 8 | 3 1 9 | 10 | Opaque 11 | 1 12 | 13 | MeshType 14 | 0 15 | -------------------------------------------------------------------------------- /Res/Blocks/DeadShrub.block: -------------------------------------------------------------------------------- 1 | Name 2 | Dead Shrub 3 | 4 | Id 5 | 11 6 | 7 | TexAll 8 | 12 0 9 | 10 | Opaque 11 | 0 12 | 13 | MeshType 14 | 1 15 | 16 | ShaderType 17 | 2 18 | 19 | Collidable 20 | 0 21 | -------------------------------------------------------------------------------- /Res/Blocks/Dirt.block: -------------------------------------------------------------------------------- 1 | Name 2 | Dirt 3 | 4 | Id 5 | 2 6 | 7 | TexAll 8 | 2 0 9 | 10 | Opaque 11 | 1 12 | 13 | MeshType 14 | 0 15 | 16 | ShaderType 17 | 0 18 | 19 | Collidable 20 | 1 21 | -------------------------------------------------------------------------------- /Res/Blocks/Glass.block: -------------------------------------------------------------------------------- 1 | Name 2 | Glass 3 | 4 | Id 5 | 14 6 | 7 | TexAll 8 | 7 1 9 | 10 | Opaque 11 | 0 12 | 13 | MeshType 14 | 0 15 | 16 | ShaderType 17 | 0 18 | 19 | Collidable 20 | 1 21 | 22 | -------------------------------------------------------------------------------- /Res/Blocks/GlassBorderless.block: -------------------------------------------------------------------------------- 1 | Name 2 | GlassBorderless 3 | 4 | Id 5 | 15 6 | 7 | TexAll 8 | 8 1 9 | 10 | Opaque 11 | 0 12 | 13 | MeshType 14 | 0 15 | 16 | ShaderType 17 | 0 18 | 19 | Collidable 20 | 1 21 | -------------------------------------------------------------------------------- /Res/Blocks/Grass.block: -------------------------------------------------------------------------------- 1 | Name 2 | Grass 3 | 4 | Id 5 | 1 6 | 7 | TexTop 8 | 0 0 9 | 10 | TexSide 11 | 1 0 12 | 13 | TexBottom 14 | 2 0 15 | 16 | Opaque 17 | 1 18 | 19 | MeshType 20 | 0 21 | 22 | ShaderType 23 | 0 24 | 25 | Collidable 26 | 1 27 | -------------------------------------------------------------------------------- /Res/Blocks/OakBark.block: -------------------------------------------------------------------------------- 1 | Name 2 | OakBark 3 | 4 | Id 5 | 4 6 | 7 | TexTop 8 | 5 0 9 | 10 | TexSide 11 | 4 0 12 | 13 | TexBottom 14 | 5 0 15 | 16 | Opaque 17 | 1 18 | 19 | MeshType 20 | 0 21 | 22 | ShaderType 23 | 0 24 | 25 | Collidable 26 | 1 27 | -------------------------------------------------------------------------------- /Res/Blocks/OakLeaf.block: -------------------------------------------------------------------------------- 1 | Name 2 | Oak Leaf 3 | 4 | Id 5 | 5 6 | 7 | TexAll 8 | 6 0 9 | 10 | Opaque 11 | 0 12 | 13 | MeshType 14 | 0 15 | 16 | ShaderType 17 | 2 18 | 19 | Collidable 20 | 1 21 | -------------------------------------------------------------------------------- /Res/Blocks/OakPlank.block: -------------------------------------------------------------------------------- 1 | Name 2 | OakPlank 3 | 4 | Id 5 | 11 6 | 7 | TexTop 8 | 5 0 9 | 10 | TexAll 11 | 4 0 12 | 13 | Opaque 14 | 1 15 | 16 | MeshType 17 | 0 18 | 19 | ShaderType 20 | 0 21 | 22 | Collidable 23 | 1 24 | -------------------------------------------------------------------------------- /Res/Blocks/OakSapling.block: -------------------------------------------------------------------------------- 1 | Name 2 | OakSapling 3 | 4 | Id 5 | 12 6 | 7 | TexAll 8 | 12 0 9 | 10 | Opaque 11 | 0 12 | 13 | MeshType 14 | 1 15 | 16 | ShaderType 17 | 2 18 | 19 | Collidable 20 | 0 21 | -------------------------------------------------------------------------------- /Res/Blocks/Rose.block: -------------------------------------------------------------------------------- 1 | Name 2 | Rose 3 | 4 | Id 5 | 9 6 | 7 | TexAll 8 | 10 0 9 | 10 | Opaque 11 | 0 12 | 13 | MeshType 14 | 1 15 | 16 | ShaderType 17 | 2 18 | 19 | Collidable 20 | 0 21 | -------------------------------------------------------------------------------- /Res/Blocks/Sand.block: -------------------------------------------------------------------------------- 1 | Name 2 | Sand 3 | 4 | Id 5 | 6 6 | 7 | TexAll 8 | 7 0 9 | 10 | Opaque 11 | 1 12 | 13 | MeshType 14 | 0 15 | 16 | ShaderType 17 | 0 18 | 19 | Collidable 20 | 1 21 | -------------------------------------------------------------------------------- /Res/Blocks/Stone.block: -------------------------------------------------------------------------------- 1 | Name 2 | Stone 3 | 4 | Id 5 | 3 6 | 7 | TexAll 8 | 3 0 9 | 10 | Opaque 11 | 1 12 | 13 | MeshType 14 | 0 15 | 16 | ShaderType 17 | 0 18 | 19 | Collidable 20 | 1 21 | -------------------------------------------------------------------------------- /Res/Blocks/TallGrass.block: -------------------------------------------------------------------------------- 1 | Name 2 | Tall Grass 3 | 4 | Id 5 | 10 6 | 7 | TexAll 8 | 11 0 9 | 10 | Opaque 11 | 0 12 | 13 | MeshType 14 | 1 15 | 16 | ShaderType 17 | 2 18 | 19 | Collidable 20 | 0 21 | -------------------------------------------------------------------------------- /Res/Blocks/Water.block: -------------------------------------------------------------------------------- 1 | Name 2 | Water 3 | 4 | Id 5 | 7 6 | 7 | TexAll 8 | 8 0 9 | 10 | Opaque 11 | 0 12 | 13 | MeshType 14 | 0 15 | 16 | ShaderType 17 | 1 18 | 19 | Collidable 20 | 0 21 | -------------------------------------------------------------------------------- /Res/Fonts/rs.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Fonts/rs.ttf -------------------------------------------------------------------------------- /Res/Textures/DefaultPack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/DefaultPack.png -------------------------------------------------------------------------------- /Res/Textures/DefaultPack2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/DefaultPack2.png -------------------------------------------------------------------------------- /Res/Textures/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/back.png -------------------------------------------------------------------------------- /Res/Textures/bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/bottom.png -------------------------------------------------------------------------------- /Res/Textures/bottomsb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/bottomsb.png -------------------------------------------------------------------------------- /Res/Textures/ch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/ch.png -------------------------------------------------------------------------------- /Res/Textures/db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/db.png -------------------------------------------------------------------------------- /Res/Textures/dm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/dm.png -------------------------------------------------------------------------------- /Res/Textures/dt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/dt.png -------------------------------------------------------------------------------- /Res/Textures/front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/front.png -------------------------------------------------------------------------------- /Res/Textures/left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/left.png -------------------------------------------------------------------------------- /Res/Textures/middlesb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/middlesb.png -------------------------------------------------------------------------------- /Res/Textures/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/right.png -------------------------------------------------------------------------------- /Res/Textures/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/test.png -------------------------------------------------------------------------------- /Res/Textures/top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/top.png -------------------------------------------------------------------------------- /Res/Textures/topsb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srcres258/minecraft-rust/50acf6e7ccda2530a5c3d9f9c8977dfdee96d6b4/Res/Textures/topsb.png -------------------------------------------------------------------------------- /Res/info.txt: -------------------------------------------------------------------------------- 1 | 2 | ============ WELCOME TO MINECRAFT RUST ============ 3 | This is a very simple Minecraft clone (mostly) created in one week 4 | 5 | 6 | Because it was made in a week, some major features were missing: 7 | -Level loading (Chunks do not save! So, I wouldn't commit to a build here for now) 8 | -Caves 9 | -Mobs 10 | -Crafting 11 | 12 | However, I did manage to implement some other important things: 13 | -World generation 14 | -Simple resource collection 15 | -Biomes 16 | -Collision detection 17 | -Block breaking/ placing 18 | 19 | 20 | For now, the game it pretty much entirely a community-driven project. 21 | Source code can be found at https://github.com/srcres258/minecraft-rust 22 | Feel free to contribute! 23 | 24 | Please view 'controls.txt for controls! 25 | 26 | ==================================================== 27 | -------------------------------------------------------------------------------- /Shaders/Basic.frag: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #version 330 18 | 19 | out vec4 outColour; 20 | in vec2 passTextureCoord; 21 | 22 | uniform sampler2D texSampler; 23 | 24 | void main() { 25 | vec4 color = texture(texSampler, passTextureCoord); 26 | 27 | outColour = color; 28 | } 29 | -------------------------------------------------------------------------------- /Shaders/Basic.vert: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #version 330 18 | 19 | layout(location = 0) in vec3 inVertexPosition; 20 | layout(location = 1) in vec2 inTextureCoord; 21 | 22 | out vec2 passTextureCoord; 23 | 24 | uniform mat4 projViewMatrix; 25 | uniform mat4 modelMatrix; 26 | 27 | void main() { 28 | gl_Position = projViewMatrix * modelMatrix * vec4(inVertexPosition, 1.0); 29 | 30 | passTextureCoord = inTextureCoord; 31 | } 32 | -------------------------------------------------------------------------------- /Shaders/Chunk.frag: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #version 330 18 | 19 | out vec4 outColour; 20 | in vec2 passTextureCoord; 21 | in float passCardinalLight; 22 | 23 | uniform sampler2D texSampler; 24 | 25 | vec4 color; 26 | 27 | void main() { 28 | color = texture(texSampler, passTextureCoord); 29 | 30 | outColour = color * passCardinalLight; 31 | if (outColour.a == 0) 32 | discard; 33 | } 34 | -------------------------------------------------------------------------------- /Shaders/Chunk.vert: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #version 330 18 | 19 | layout(location = 0) in vec3 inVertexPosition; 20 | layout(location = 1) in vec2 inTextureCoord; 21 | layout(location = 2) in float inCardinalLight; 22 | 23 | out vec2 passTextureCoord; 24 | out float passCardinalLight; 25 | 26 | uniform mat4 projViewMatrix; 27 | 28 | void main() { 29 | gl_Position = projViewMatrix * vec4(inVertexPosition, 1.0); 30 | 31 | passTextureCoord = inTextureCoord; 32 | passCardinalLight = inCardinalLight; 33 | } 34 | -------------------------------------------------------------------------------- /Shaders/Flora.vert: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #version 330 18 | 19 | layout(location = 0) in vec3 inVertexPosition; 20 | layout(location = 1) in vec2 inTextureCoord; 21 | layout(location = 2) in float inCardinalLight; 22 | 23 | out vec2 passTextureCoord; 24 | out float passCardinalLight; 25 | 26 | uniform mat4 projViewMatrix; 27 | uniform float globalTime; 28 | 29 | 30 | vec4 getWorldPos() { 31 | vec3 inVert = inVertexPosition.xyz; 32 | inVert.x += sin((globalTime + inVert.z + inVert.y) * 1.8f) / 15.0f; 33 | inVert.z -= cos((globalTime + inVert.x + inVert.y) * 1.8f) / 15.0f; 34 | return vec4(inVert, 1); 35 | } 36 | 37 | void main() { 38 | gl_Position = projViewMatrix * getWorldPos(); 39 | 40 | passTextureCoord = inTextureCoord; 41 | passCardinalLight = inCardinalLight; 42 | } 43 | -------------------------------------------------------------------------------- /Shaders/Skybox.frag: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #version 330 18 | 19 | out vec4 outColour; 20 | in vec3 passTextureCoord; 21 | 22 | uniform samplerCube texSampler; 23 | 24 | vec3 brightnessContrast(vec3 value, float brightness, float contrast) { 25 | return (value - 0.5) * contrast + 0.5 + (brightness-1); 26 | } 27 | 28 | vec4 color; 29 | 30 | vec3 gamma(vec3 value, float param) { 31 | return vec3( 32 | pow(abs(value.r), param), 33 | pow(abs(value.g), param), 34 | pow(abs(value.b), param) 35 | ); 36 | } 37 | 38 | 39 | void main() { 40 | color = texture(texSampler, passTextureCoord); 41 | color = vec4(brightnessContrast(color.xyz, 1.15f, 1.15f), color.w); 42 | color = vec4(gamma(color.xyz, 4.8f),color.w); 43 | 44 | outColour = color; 45 | if (outColour.a == 0) discard; 46 | } 47 | -------------------------------------------------------------------------------- /Shaders/Skybox.vert: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #version 330 18 | 19 | layout(location = 0) in vec3 inVertexPosition; 20 | 21 | out vec3 passTextureCoord; 22 | 23 | uniform mat4 projectionMatrix; 24 | uniform mat4 viewMatrix; 25 | 26 | void main() { 27 | gl_Position = projectionMatrix * viewMatrix * vec4(inVertexPosition, 1.0); 28 | 29 | passTextureCoord = inVertexPosition; 30 | } 31 | -------------------------------------------------------------------------------- /Shaders/Water.vert: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #version 330 18 | 19 | layout(location = 0) in vec3 inVertexPosition; 20 | layout(location = 1) in vec2 inTextureCoord; 21 | layout(location = 2) in float inCardinalLight; 22 | 23 | out vec2 passTextureCoord; 24 | out float passCardinalLight; 25 | 26 | uniform mat4 projViewMatrix; 27 | uniform float globalTime; 28 | 29 | 30 | vec4 getWorldPos() { 31 | vec3 inVert = inVertexPosition.xyz; 32 | inVert.y += sin((globalTime + inVert.x) * 1.5) / 8.8f; 33 | inVert.y += cos((globalTime + inVert.z) * 1.5) / 8.1f; 34 | inVert.y -= 0.2; 35 | return vec4(inVert, 1); 36 | } 37 | 38 | void main() { 39 | gl_Position = projViewMatrix * getWorldPos(); 40 | 41 | passTextureCoord = inTextureCoord; 42 | passCardinalLight = inCardinalLight; 43 | } 44 | -------------------------------------------------------------------------------- /src/application.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::cell::UnsafeCell; 18 | use std::rc::Rc; 19 | use std::sync::Arc; 20 | use sfml::system::{Clock, Time}; 21 | use sfml::window::{Event, Key, Window}; 22 | use crate::camera::Camera; 23 | use crate::config::Config; 24 | use crate::context::Context; 25 | use crate::renderer::render_master::RenderMaster; 26 | use crate::states::play_state::StatePlay; 27 | use crate::states::state_base::StateBase; 28 | use crate::util::unsafe_cell_wrapper::UnsafeCellWrapper; 29 | use crate::world::block::block_database::BlockDatabase; 30 | 31 | pub static mut TIME_ELAPSED: f32 = 0.0; 32 | 33 | /// @brief The main game application itself. 34 | pub struct Application { 35 | states: Vec>, 36 | context: Context, 37 | master_renderer: RenderMaster, 38 | camera: Arc>, 39 | #[allow(dead_code)] 40 | config: Config, 41 | is_pop_state: bool 42 | } 43 | 44 | impl Application { 45 | pub fn new(config: Config) -> Rc> { 46 | let result = Self { 47 | states: Vec::new(), 48 | context: Context::new(config), 49 | master_renderer: RenderMaster::default(), 50 | camera: Arc::new(UnsafeCellWrapper::new(Camera::new(config))), 51 | config, 52 | is_pop_state: false 53 | }; 54 | let result = Rc::new(UnsafeCell::new(result)); 55 | 56 | BlockDatabase::get(); 57 | unsafe { 58 | (*result.get()).push_state(StatePlay::new_boxed(Rc::clone(&result), config)); 59 | } 60 | 61 | result 62 | } 63 | 64 | /// @brief Game loop utilizing a mixture of SFML events and GL rendering. 65 | pub fn run_loop(&mut self) { 66 | let mut dt_timer = Clock::start(); 67 | let mut dt = Clock::start(); 68 | 69 | #[allow(unused_assignments)] 70 | let mut m = Time::default(); 71 | 72 | while self.context.window.is_open() && !self.states.is_empty() { 73 | let delta_time = dt_timer.restart(); 74 | let state = self.states.last_mut().unwrap(); 75 | 76 | state.handle_input(); 77 | state.update(delta_time.as_seconds()); 78 | unsafe { 79 | (*self.camera.get()).update(); 80 | } 81 | 82 | state.render(&mut self.master_renderer); 83 | unsafe { 84 | self.master_renderer.finish_render(&mut self.context.window, &*self.camera.get()); 85 | } 86 | 87 | self.handle_events(); 88 | if self.is_pop_state { 89 | self.is_pop_state = false; 90 | self.states.pop(); 91 | } 92 | 93 | m = dt.restart(); 94 | 95 | unsafe { 96 | TIME_ELAPSED += m.as_seconds(); 97 | } 98 | } 99 | } 100 | 101 | /// @brief Handles window events, especially window polling and keyboard inputs. 102 | pub fn push_state(&mut self, state: Box) { 103 | self.states.push(state); 104 | let s = self.states.last_mut().unwrap(); 105 | s.on_open(); 106 | } 107 | 108 | /// @brief Tell the program stack to pop off the state. 109 | pub fn pop_state(&mut self) { 110 | self.is_pop_state = true; 111 | } 112 | 113 | pub fn camera(&self) -> Arc> { 114 | Arc::clone(&self.camera) 115 | } 116 | 117 | pub fn window(&self) -> &Window { 118 | &self.context.window 119 | } 120 | 121 | pub fn window_mut(&mut self) -> &mut Window { 122 | &mut self.context.window 123 | } 124 | 125 | /// @brief Makes the mouse invisible, doesn't actually turn off the mouse 126 | pub fn turn_off_mouse(&mut self) { 127 | self.context.window.set_mouse_cursor_visible(false); 128 | } 129 | 130 | /// @brief Makes the mouse visible again. 131 | pub fn turn_on_mouse(&mut self) { 132 | self.context.window.set_mouse_cursor_visible(true); 133 | } 134 | 135 | /// @brief Handles window events, especially window polling and keyboard inputs. 136 | fn handle_events(&mut self) { 137 | while let Some(e) = self.context.window.poll_event() { 138 | self.states.last_mut().unwrap().handle_event(e); 139 | match e { 140 | Event::Closed => { 141 | self.context.window.close(); 142 | } 143 | Event::KeyPressed { code, .. } => { 144 | match code { 145 | Key::Escape => { 146 | self.context.window.close(); 147 | } 148 | _ => {} 149 | } 150 | } 151 | _ => {} 152 | } 153 | } 154 | } 155 | } -------------------------------------------------------------------------------- /src/camera.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | extern crate nalgebra_glm as glm; 18 | 19 | use std::ops::{Deref, DerefMut}; 20 | use crate::config::Config; 21 | use crate::entity::Entity; 22 | use crate::maths::frustum::ViewFrustum; 23 | use crate::maths::matrix; 24 | 25 | pub struct PtrConstEntity(*const Entity); 26 | 27 | pub struct Camera { 28 | pub base: Entity, 29 | 30 | p_entity: Option, 31 | 32 | frustum: ViewFrustum, 33 | 34 | projection_matrix: glm::TMat4, 35 | view_matrix: glm::TMat4, 36 | proj_view_matrix: glm::TMat4, 37 | 38 | #[allow(dead_code)] 39 | config: Config 40 | } 41 | 42 | impl Deref for PtrConstEntity { 43 | type Target = *const Entity; 44 | 45 | fn deref(&self) -> &Self::Target { 46 | &self.0 47 | } 48 | } 49 | 50 | impl DerefMut for PtrConstEntity { 51 | fn deref_mut(&mut self) -> &mut Self::Target { 52 | &mut self.0 53 | } 54 | } 55 | 56 | unsafe impl Send for PtrConstEntity {} 57 | 58 | impl Camera { 59 | pub fn new(config: Config) -> Self { 60 | let mut obj = Entity::default(); 61 | obj.position = glm::vec3(0., 0., -3.5); 62 | let projection_matrix = matrix::make_projection_matrix(&config); 63 | 64 | Self { 65 | base: obj, 66 | p_entity: None, 67 | frustum: ViewFrustum::default(), 68 | projection_matrix, 69 | view_matrix: Default::default(), 70 | proj_view_matrix: Default::default(), 71 | config 72 | } 73 | } 74 | 75 | pub fn update(&mut self) { 76 | let wrapped_obj = &mut self.base; 77 | let p_entity = unsafe { &***self.p_entity.as_ref().unwrap() }; 78 | wrapped_obj.position = glm::vec3( 79 | p_entity.position.x, p_entity.position.y + 0.6, p_entity.position.z 80 | ); 81 | wrapped_obj.rotation = p_entity.rotation; 82 | 83 | self.view_matrix = matrix::make_view_matrix(self); 84 | self.proj_view_matrix = self.projection_matrix * self.view_matrix; 85 | self.frustum.update(&self.proj_view_matrix); 86 | 87 | // println!("Camera frustum: {:#?}", self.frustum); 88 | } 89 | 90 | pub fn hook_entity(&mut self, entity: *const Entity) { 91 | self.p_entity = Some(PtrConstEntity(entity)); 92 | } 93 | 94 | pub fn get_view_matrix(&self) -> glm::TMat4 { 95 | self.view_matrix 96 | } 97 | 98 | pub fn get_proj_matrix(&self) -> glm::TMat4 { 99 | self.projection_matrix 100 | } 101 | 102 | pub fn get_projection_view_matrix(&self) -> glm::TMat4 { 103 | self.proj_view_matrix 104 | } 105 | 106 | pub fn get_frustum(&self) -> &ViewFrustum { 107 | &self.frustum 108 | } 109 | } 110 | 111 | impl Deref for Camera { 112 | type Target = Entity; 113 | 114 | fn deref(&self) -> &Self::Target { 115 | &self.base 116 | } 117 | } 118 | 119 | impl DerefMut for Camera { 120 | fn deref_mut(&mut self) -> &mut Self::Target { 121 | &mut self.base 122 | } 123 | } -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | /// @brief Default configuration for program. 18 | #[derive(Copy, Clone)] 19 | pub struct Config { 20 | pub window_x: i32, 21 | pub window_y: i32, 22 | pub is_fullscreen: bool, 23 | pub render_distance: i32, // Set initial RD low to prevent long load times 24 | pub fov: i32 25 | } 26 | 27 | impl Default for Config { 28 | fn default() -> Self { 29 | Self { 30 | window_x: 1280, 31 | window_y: 720, 32 | is_fullscreen: false, 33 | render_distance: 8, 34 | fov: 90 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/context.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::ffi::{c_void, CStr}; 18 | use std::ptr; 19 | use gl::types::{GLchar, GLenum, GLsizei, GLuint}; 20 | use sfml::window::{ContextSettings, Style, VideoMode, Window}; 21 | use crate::config::Config; 22 | 23 | pub struct Context { 24 | pub window: Window 25 | } 26 | 27 | impl Context { 28 | pub fn new(config: Config) -> Self { 29 | let mut settings = ContextSettings::default(); 30 | settings.antialiasing_level = 0; 31 | settings.major_version = 3; 32 | settings.minor_version = 3; 33 | settings.depth_bits = 24; 34 | settings.stencil_bits = 8; 35 | 36 | let result = Self { 37 | window: if config.is_fullscreen { 38 | Window::new( 39 | VideoMode::desktop_mode(), 40 | "minecraft-rust", 41 | Style::FULLSCREEN, 42 | &settings 43 | ) 44 | } else { 45 | let win_mode = VideoMode::new( 46 | config.window_x as _, 47 | config.window_y as _, 48 | 32 49 | ); 50 | Window::new(win_mode, "minecraft-rust", Style::CLOSE, &settings) 51 | } 52 | }; 53 | 54 | // Load OpenGL library. 55 | gl_loader::init_gl(); 56 | // Load all the OpenGL function pointer using the `gl` crate. 57 | gl::load_with(|symbol| gl_loader::get_proc_address(symbol) as *const _); 58 | // Unload the OpenGL library. 59 | gl_loader::end_gl(); 60 | 61 | unsafe { 62 | gl::Enable(gl::DEBUG_OUTPUT); 63 | // makes sure errors are displayed synchronously 64 | gl::Enable(gl::DEBUG_OUTPUT_SYNCHRONOUS); 65 | gl::DebugMessageCallback(Some(gl_debug_output), ptr::null()); 66 | gl::DebugMessageControl( 67 | gl::DONT_CARE, 68 | gl::DONT_CARE, 69 | gl::DONT_CARE, 70 | 0, 71 | ptr::null(), 72 | gl::TRUE 73 | ); 74 | 75 | gl::Viewport(0, 0, result.window.size().x as _, result.window.size().y as _); 76 | 77 | gl::CullFace(gl::BACK); 78 | gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); 79 | } 80 | 81 | result 82 | } 83 | } 84 | 85 | extern "system" fn gl_debug_output( 86 | source: GLenum, 87 | gltype: GLenum, 88 | id: GLuint, 89 | severity: GLenum, 90 | _length: GLsizei, 91 | message: *const GLchar, 92 | _user_param: *mut c_void 93 | ) { 94 | // ignore these non-significant error codes 95 | if id == 131169 || id == 131185 || id == 131218 || id == 131204 { 96 | return; 97 | } 98 | 99 | let message_c_str; 100 | unsafe { 101 | message_c_str = CStr::from_ptr(message); 102 | } 103 | let message_str = message_c_str.to_str().unwrap(); 104 | log::debug!("Debug message ({}): {}", id, message_str); 105 | match source { 106 | gl::DEBUG_SOURCE_API => log::debug!("Source: API"), 107 | gl::DEBUG_SOURCE_WINDOW_SYSTEM => log::debug!("Source: Window System"), 108 | gl::DEBUG_SOURCE_SHADER_COMPILER => log::debug!("Source: Shader Compiler"), 109 | gl::DEBUG_SOURCE_THIRD_PARTY => log::debug!("Source: Third Party"), 110 | gl::DEBUG_SOURCE_APPLICATION => log::debug!("Source: Application"), 111 | gl::DEBUG_SOURCE_OTHER => log::debug!("Source: Other"), 112 | _ => {} 113 | } 114 | match gltype { 115 | gl::DEBUG_TYPE_ERROR => log::debug!("Type: Error"), 116 | gl::DEBUG_TYPE_DEPRECATED_BEHAVIOR => log::debug!("Type: Deprecated Behaviour"), 117 | gl::DEBUG_TYPE_UNDEFINED_BEHAVIOR => log::debug!("Type: Undefined Behaviour"), 118 | gl::DEBUG_TYPE_PORTABILITY => log::debug!("Type: Portability"), 119 | gl::DEBUG_TYPE_PERFORMANCE => log::debug!("Type: Performance"), 120 | gl::DEBUG_TYPE_MARKER => log::debug!("Type: Marker"), 121 | gl::DEBUG_TYPE_PUSH_GROUP => log::debug!("Type: Push Group"), 122 | gl::DEBUG_TYPE_POP_GROUP => log::debug!("Type: Pop Group"), 123 | gl::DEBUG_TYPE_OTHER => log::debug!("Type: Other"), 124 | _ => {} 125 | } 126 | match severity { 127 | gl::DEBUG_SEVERITY_HIGH => log::debug!("Severity: high"), 128 | gl::DEBUG_SEVERITY_MEDIUM => log::debug!("Severity: medium"), 129 | gl::DEBUG_SEVERITY_LOW => log::debug!("Severity: low"), 130 | gl::DEBUG_SEVERITY_NOTIFICATION => log::debug!("Severity: notification"), 131 | _ => {} 132 | } 133 | log::debug!("---------------"); 134 | } -------------------------------------------------------------------------------- /src/entity.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | extern crate nalgebra_glm as glm; 18 | 19 | use crate::physics::aabb::AABB; 20 | 21 | #[derive(Copy, Clone)] 22 | pub struct Entity { 23 | pub position: glm::TVec3, 24 | pub rotation: glm::TVec3, 25 | pub velocity: glm::TVec3, 26 | 27 | pub box_aabb: AABB 28 | } 29 | 30 | impl Entity { 31 | pub fn new() -> Self { 32 | Self::default() 33 | } 34 | 35 | pub fn new_ex_1(pos: &glm::TVec3, rot: &glm::TVec3) -> Self { 36 | Self { 37 | position: *pos, 38 | rotation: *rot, 39 | velocity: glm::vec3(0.0, 0.0, 0.0), 40 | box_aabb: AABB::new(&glm::vec3(0.0, 0.0, 0.0)) 41 | } 42 | } 43 | 44 | pub fn new_ex_2( 45 | pos: &glm::TVec3, 46 | rot: &glm::TVec3, 47 | box_aabb: &glm::TVec3 48 | ) -> Self { 49 | Self { 50 | position: *pos, 51 | rotation: *rot, 52 | velocity: glm::vec3(0.0, 0.0, 0.0), 53 | box_aabb: AABB::new(box_aabb) 54 | } 55 | } 56 | } 57 | 58 | impl Default for Entity { 59 | fn default() -> Self { 60 | Self { 61 | position: glm::vec3(0.0, 0.0, 0.0), 62 | rotation: glm::vec3(0.0, 0.0, 0.0), 63 | velocity: glm::vec3(0.0, 0.0, 0.0), 64 | box_aabb: AABB::new(&glm::vec3(0.0, 0.0, 0.0)) 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /src/gl/gl_functions.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::ptr; 18 | use gl::types::{GLsizei, GLuint}; 19 | 20 | pub fn draw_elements(indices_count: GLsizei) { 21 | unsafe { 22 | gl::DrawElements(gl::TRIANGLES, indices_count, gl::UNSIGNED_INT, ptr::null()); 23 | } 24 | } 25 | 26 | pub fn bind_vao(vao: GLuint) { 27 | unsafe { 28 | gl::BindVertexArray(vao); 29 | } 30 | } -------------------------------------------------------------------------------- /src/gl/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod gl_functions; -------------------------------------------------------------------------------- /src/input/keyboard.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::collections::HashMap; 18 | use sfml::window::{Event, Key}; 19 | 20 | /// @brief Handles keyboard inputs and events. 21 | pub struct Keyboard { 22 | keys: HashMap, 23 | recently_released: Key 24 | } 25 | 26 | impl Keyboard { 27 | pub fn new() -> Self { 28 | Self { 29 | keys: HashMap::new(), 30 | recently_released: Key::Unknown 31 | } 32 | } 33 | 34 | pub fn update(&mut self, e: Event) { 35 | match e { 36 | Event::KeyReleased { code, .. } => { 37 | self.keys.insert(code, false); 38 | } 39 | Event::KeyPressed { code, .. } => { 40 | self.recently_released = code; 41 | self.keys.insert(code, true); 42 | } 43 | _ => {} 44 | } 45 | } 46 | 47 | pub fn is_key_down(&self, key: Key) -> bool { 48 | *self.keys.get(&key).unwrap_or(&false) 49 | } 50 | 51 | pub fn key_released(&self, key: Key) -> bool { 52 | self.recently_released == key 53 | } 54 | } -------------------------------------------------------------------------------- /src/input/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod keyboard; 18 | pub mod toggle_key; -------------------------------------------------------------------------------- /src/input/toggle_key.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use sfml::SfBox; 18 | use sfml::system::Clock; 19 | use sfml::window::Key; 20 | 21 | /// @brief A keyboard related subclass that determines if a key remains pressed. 22 | pub struct ToggleKey { 23 | key: Key, 24 | delay_timer: SfBox 25 | } 26 | 27 | impl ToggleKey { 28 | pub fn new(key: Key) -> Self { 29 | Self { 30 | key, 31 | delay_timer: Clock::start() 32 | } 33 | } 34 | 35 | pub fn is_key_pressed(&mut self) -> bool { 36 | if self.delay_timer.elapsed_time().as_seconds() > 0.2 { 37 | if self.key.is_pressed() { 38 | self.delay_timer.restart(); 39 | return true; 40 | } 41 | } 42 | false 43 | } 44 | } -------------------------------------------------------------------------------- /src/item/item_stack.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::item::material; 18 | use crate::item::material::Material; 19 | 20 | /// @brief Determines if a player character is holding blocks or items, also determines placement behavior. 21 | pub struct ItemStack { 22 | p_material: &'static Material, 23 | num_in_stack: i32 24 | } 25 | 26 | impl ItemStack { 27 | pub fn new(material: &'static Material, amount: i32) -> Self { 28 | Self { 29 | p_material: material, 30 | num_in_stack: amount 31 | } 32 | } 33 | 34 | pub fn add(&mut self, amount: i32) -> i32 { 35 | self.num_in_stack += amount; 36 | 37 | if self.num_in_stack > self.p_material.max_stack_size { 38 | let left_over = self.num_in_stack - self.p_material.max_stack_size; 39 | self.num_in_stack = self.p_material.max_stack_size; 40 | left_over 41 | } else { 42 | 0 43 | } 44 | } 45 | 46 | pub fn remove(&mut self) { 47 | self.num_in_stack -= 1; 48 | if self.num_in_stack == 0 { 49 | self.p_material = &material::NOTHING; 50 | } 51 | } 52 | 53 | pub fn num_in_stack(&self) -> i32 { 54 | self.num_in_stack 55 | } 56 | 57 | pub fn material(&self) -> &'static Material { 58 | self.p_material 59 | } 60 | } -------------------------------------------------------------------------------- /src/item/material.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use lazy_static::lazy_static; 18 | use crate::world::block::block_id::BlockId; 19 | 20 | #[derive(Copy, Clone, Eq, PartialEq)] 21 | pub enum ID { 22 | Nothing, 23 | Grass, 24 | Dirt, 25 | Stone, 26 | OakBark, 27 | OakLeaf, 28 | Sand, 29 | Cactus, 30 | Rose, 31 | TallGrass, 32 | DeadShrub 33 | } 34 | 35 | /// @brief Determines case-by-case properties and behaviors of known block types. 36 | pub struct Material { 37 | pub id: ID, 38 | pub max_stack_size: i32, 39 | pub is_block: bool, 40 | pub name: String 41 | } 42 | 43 | impl Material { 44 | pub fn new( 45 | id: ID, 46 | max_stack_size: i32, 47 | is_block: bool, 48 | name: &str 49 | ) -> Self { 50 | Self { 51 | id, 52 | max_stack_size, 53 | is_block, 54 | name: String::from(name) 55 | } 56 | } 57 | 58 | pub fn to_block_id(&self) -> BlockId { 59 | match self.id { 60 | ID::Nothing => BlockId::Air, 61 | ID::Grass => BlockId::Grass, 62 | ID::Dirt => BlockId::Dirt, 63 | ID::Stone => BlockId::Stone, 64 | ID::OakBark => BlockId::OakBark, 65 | ID::OakLeaf => BlockId::OakLeaf, 66 | ID::Sand => BlockId::Sand, 67 | ID::Cactus => BlockId::Cactus, 68 | ID::TallGrass => BlockId::TallGrass, 69 | ID::Rose => BlockId::Rose, 70 | ID::DeadShrub => BlockId::DeadShrub 71 | } 72 | } 73 | 74 | pub fn from_block_id(id: BlockId) -> &'static Material { 75 | match id { 76 | BlockId::Grass => &GRASS_BLOCK, 77 | BlockId::Dirt => &DIRT_BLOCK, 78 | BlockId::Stone => &STONE_BLOCK, 79 | BlockId::OakBark => &OAK_BARK_BLOCK, 80 | BlockId::OakLeaf => &OAK_LEAF_BLOCK, 81 | BlockId::Sand => &SAND_BLOCK, 82 | BlockId::Cactus => &CACTUS_BLOCK, 83 | BlockId::Rose => &ROSE, 84 | BlockId::TallGrass => &TALL_GRASS, 85 | BlockId::DeadShrub => &DEAD_SHRUB, 86 | _ => &NOTHING 87 | } 88 | } 89 | } 90 | 91 | lazy_static! { 92 | pub static ref NOTHING: Material = Material::new( 93 | ID::Nothing, 0, false, "None" 94 | ); 95 | pub static ref GRASS_BLOCK: Material = Material::new( 96 | ID::Grass, 99, true, "Grass Block" 97 | ); 98 | pub static ref DIRT_BLOCK: Material = Material::new( 99 | ID::Dirt, 99, true, "Dirt Block" 100 | ); 101 | pub static ref STONE_BLOCK: Material = Material::new( 102 | ID::Stone, 99, true, "Stone Block" 103 | ); 104 | pub static ref OAK_BARK_BLOCK: Material = Material::new( 105 | ID::OakBark, 99, true, "Oak Bark Block" 106 | ); 107 | pub static ref OAK_LEAF_BLOCK: Material = Material::new( 108 | ID::OakLeaf, 99, true, "Oak Leaf Block" 109 | ); 110 | pub static ref SAND_BLOCK: Material = Material::new( 111 | ID::Sand, 99, true, "Sand Block" 112 | ); 113 | pub static ref CACTUS_BLOCK: Material = Material::new( 114 | ID::Cactus, 99, true, "Cactus Block" 115 | ); 116 | 117 | pub static ref ROSE: Material = Material::new( 118 | ID::Rose, 99, true, "Rose" 119 | ); 120 | pub static ref TALL_GRASS: Material = Material::new( 121 | ID::TallGrass, 99, true, "Tall Grass" 122 | ); 123 | pub static ref DEAD_SHRUB: Material = Material::new( 124 | ID::DeadShrub, 99, true, "Dead Shrub" 125 | ); 126 | } -------------------------------------------------------------------------------- /src/item/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod item_stack; 18 | pub mod material; -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::fs; 18 | use std::fs::File; 19 | use std::io::{BufRead, BufReader, BufWriter, Write}; 20 | use std::path::Path; 21 | use crate::application::Application; 22 | use crate::config::Config; 23 | 24 | pub mod application; 25 | pub mod states; 26 | pub mod context; 27 | pub mod renderer; 28 | pub mod camera; 29 | pub mod entity; 30 | pub mod physics; 31 | pub mod config; 32 | pub mod input; 33 | pub mod player; 34 | pub mod item; 35 | pub mod world; 36 | pub mod util; 37 | pub mod maths; 38 | pub mod mesh; 39 | pub mod model; 40 | pub mod texture; 41 | pub mod shaders; 42 | pub mod gl; 43 | 44 | /// @brief Self declared function that loads in configuration files as needed. 45 | /// @param config 46 | fn load_config(config: &mut Config) { 47 | let config_file = Path::new("config.txt"); 48 | 49 | // If the config file is missing or "bad" 50 | if !config_file.exists() { 51 | log::debug!("Configuration file invalid, writing 'new' configuration."); 52 | 53 | let out_file = File::create(config_file).unwrap(); 54 | let mut writer = BufWriter::new(out_file); 55 | writer.write(b"renderdistance 8\n").unwrap(); 56 | writer.write(b"fullscreen 0\n").unwrap(); 57 | writer.write(b"windowsize 1600 900\n").unwrap(); 58 | writer.write(b"fov 105\n").unwrap(); 59 | writer.flush().unwrap(); 60 | 61 | log::debug!("New configuration file created."); 62 | } 63 | 64 | // Open 'new' config file. 65 | let config_file = File::open(config_file) 66 | .expect("Unable to load configuration file."); 67 | let reader = BufReader::new(config_file); 68 | for line in reader.lines() { 69 | let line = line.unwrap(); 70 | let line = line.trim(); 71 | let parts: Vec<_> = line.split(' ').collect(); 72 | if parts.len() > 0 { 73 | let key = parts[0]; 74 | if key == "renderdistance" { 75 | config.render_distance = parts[1].parse().unwrap(); 76 | log::debug!("Config: Render Distance: {}", config.render_distance); 77 | } else if key == "fullscreen" { 78 | let is_fullscreen: i32 = parts[1].parse().unwrap(); 79 | config.is_fullscreen = is_fullscreen == 1; 80 | log::debug!("Config: Full screen mode: {}", config.is_fullscreen); 81 | } else if key == "windowsize" { 82 | config.window_x = parts[1].parse().unwrap(); 83 | config.window_y = parts[2].parse().unwrap(); 84 | log::debug!("Config: Window Size: {} x {}", config.window_x, config.window_y); 85 | } else if key == "fov" { 86 | config.fov = parts[1].parse().unwrap(); 87 | log::debug!("Config: Field of Vision: {}", config.fov); 88 | } 89 | } 90 | } 91 | } 92 | 93 | fn display_info() { 94 | let info = fs::read_to_string("Res/info.txt").unwrap(); 95 | for line in info.lines() { 96 | log::info!("{}", line); 97 | } 98 | } 99 | 100 | fn main() { 101 | env_logger::init(); 102 | 103 | let mut config = Config::default(); 104 | load_config(&mut config); 105 | display_info(); 106 | 107 | log::info!("Loading game..."); 108 | 109 | let app = Application::new(config); 110 | unsafe { 111 | (*app.get()).run_loop(); 112 | } 113 | } -------------------------------------------------------------------------------- /src/maths/frustum.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | extern crate nalgebra_glm as glm; 18 | 19 | use crate::physics::aabb::AABB; 20 | 21 | pub enum Planes { 22 | Near = 0, 23 | Far, 24 | Left, 25 | Right, 26 | Top, 27 | Bottom 28 | } 29 | 30 | /// @brief Vertex based construct, usually flat. 31 | #[derive(Copy, Clone, Default, Debug)] 32 | pub struct Plane { 33 | pub distance_to_origin: f32, 34 | pub normal: glm::TVec3 // Vector3 normals 35 | } 36 | 37 | #[derive(Copy, Clone, Default, Debug)] 38 | pub struct ViewFrustum { 39 | planes: [Plane; 6] 40 | } 41 | 42 | impl Plane { 43 | pub fn new(distance_to_origin: f32, normal: glm::TVec3) -> Self { 44 | Self { distance_to_origin, normal } 45 | } 46 | 47 | pub fn distance_to_point(&self, point: &glm::TVec3) -> f32 { 48 | glm::dot(point, &self.normal) + self.distance_to_origin 49 | } 50 | } 51 | 52 | impl ViewFrustum { 53 | pub fn new(planes: [Plane; 6]) -> Self { 54 | Self { planes } 55 | } 56 | 57 | /// @brief Updates the Frustrum relative between player and observed surface. 58 | /// @param mat 59 | pub fn update(&mut self, mat: &glm::TMat4) { 60 | /* 61 | NOTE that within the nalgebra_glm crate, implementation of matrix indexing is reversed 62 | compared to that of C++ glm library. 63 | 64 | e.g. In C++ glm library we use `mat[x][y]` to refer to the element at column x and row y 65 | of the matrix. However, it is represented as `mat[(y, x)]` in nalgebra_glm. 66 | 67 | Hence, be CAREFUL about the difference between the two libraries. 68 | */ 69 | 70 | // left 71 | self.planes[Planes::Left as usize].normal.x = mat[(3, 0)] + mat[(0, 0)]; 72 | self.planes[Planes::Left as usize].normal.y = mat[(3, 1)] + mat[(0, 1)]; 73 | self.planes[Planes::Left as usize].normal.z = mat[(3, 2)] + mat[(0, 2)]; 74 | self.planes[Planes::Left as usize].distance_to_origin = mat[(3, 3)] + mat[(0, 2)]; 75 | 76 | // right 77 | self.planes[Planes::Right as usize].normal.x = mat[(3, 0)] - mat[(0, 0)]; 78 | self.planes[Planes::Right as usize].normal.y = mat[(3, 1)] - mat[(0, 1)]; 79 | self.planes[Planes::Right as usize].normal.z = mat[(3, 2)] - mat[(0, 2)]; 80 | self.planes[Planes::Right as usize].distance_to_origin = mat[(3, 3)] - mat[(0, 3)]; 81 | 82 | // bottom 83 | self.planes[Planes::Bottom as usize].normal.x = mat[(3, 0)] + mat[(1, 0)]; 84 | self.planes[Planes::Bottom as usize].normal.y = mat[(3, 1)] + mat[(1, 1)]; 85 | self.planes[Planes::Bottom as usize].normal.z = mat[(3, 2)] + mat[(1, 2)]; 86 | self.planes[Planes::Bottom as usize].distance_to_origin = mat[(3, 3)] + mat[(1, 3)]; 87 | 88 | // top 89 | self.planes[Planes::Top as usize].normal.x = mat[(3, 0)] - mat[(1, 0)]; 90 | self.planes[Planes::Top as usize].normal.y = mat[(3, 1)] - mat[(1, 1)]; 91 | self.planes[Planes::Top as usize].normal.z = mat[(3, 2)] - mat[(1, 2)]; 92 | self.planes[Planes::Top as usize].distance_to_origin = mat[(3, 3)] - mat[(1, 3)]; 93 | 94 | // near 95 | self.planes[Planes::Near as usize].normal.x = mat[(3, 0)] + mat[(2, 0)]; 96 | self.planes[Planes::Near as usize].normal.y = mat[(3, 1)] + mat[(2, 1)]; 97 | self.planes[Planes::Near as usize].normal.z = mat[(3, 2)] + mat[(2, 2)]; 98 | self.planes[Planes::Near as usize].distance_to_origin = mat[(3, 3)] + mat[(2, 3)]; 99 | 100 | // far 101 | self.planes[Planes::Far as usize].normal.x = mat[(3, 0)] - mat[(2, 0)]; 102 | self.planes[Planes::Far as usize].normal.y = mat[(3, 1)] - mat[(2, 1)]; 103 | self.planes[Planes::Far as usize].normal.z = mat[(3, 2)] - mat[(2, 2)]; 104 | self.planes[Planes::Far as usize].distance_to_origin = mat[(3, 3)] - mat[(2, 3)]; 105 | 106 | for plane in self.planes.iter_mut() { 107 | let length = glm::length(&plane.normal); 108 | plane.normal /= length; 109 | plane.distance_to_origin /= length; 110 | } 111 | } 112 | 113 | /// @brief Determines if a collision box is present in the Frustrum. 114 | /// @param box 115 | /// @return result 116 | pub fn is_box_in_frustum(&self, box_: AABB) -> bool { 117 | for plane in self.planes.iter() { 118 | if plane.distance_to_point(&box_.get_vp(plane.normal)) < 0.0 { 119 | return false; 120 | } else if plane.distance_to_point(&box_.get_vn(plane.normal)) < 0.0 { 121 | return true; 122 | } 123 | } 124 | true 125 | } 126 | } -------------------------------------------------------------------------------- /src/maths/general_maths.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | fn smooth_step(edge0: f32, edge1: f32, mut x: f32) -> f32 { 18 | // Scale, bias and saturate x to 0..1 range 19 | x = x * x * (3.0 - 2.0 * x); 20 | // Evaluate polynomial 21 | edge0 * x + edge1 * (1.0 - x) 22 | } 23 | 24 | pub fn smooth_interpolation( 25 | bottom_left: f32, 26 | top_left: f32, 27 | bottom_right: f32, 28 | top_right: f32, 29 | x_min: f32, 30 | x_max: f32, 31 | z_min: f32, 32 | z_max: f32, 33 | x: f32, 34 | z: f32 35 | ) -> f32 { 36 | let (width, height) = (x_max - x_min, z_max - z_min); 37 | let x_value = 1.0 - (x - x_min) / width; 38 | let z_value = 1.0 - (z - z_min) / height; 39 | 40 | let a = smooth_step(bottom_left, bottom_right, x_value); 41 | let b = smooth_step(top_left, top_right, x_value); 42 | 43 | smooth_step(a, b, z_value) 44 | } -------------------------------------------------------------------------------- /src/maths/matrix.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | extern crate nalgebra_glm as glm; 18 | 19 | use crate::camera::Camera; 20 | use crate::config::Config; 21 | use crate::entity::Entity; 22 | 23 | pub fn make_model_matrix(entity: &Entity) -> glm::TMat4 { 24 | let mut matrix: glm::TMat4 = Default::default(); 25 | 26 | matrix = glm::rotate( 27 | &matrix, entity.rotation.x.to_radians(), &glm::vec3(1.0, 0.0, 0.0) 28 | ); 29 | matrix = glm::rotate( 30 | &matrix, entity.rotation.y.to_radians(), &glm::vec3(0.0, 1.0, 0.0) 31 | ); 32 | matrix = glm::rotate( 33 | &matrix, entity.rotation.z.to_radians(), &glm::vec3(0.0, 0.0, 1.0) 34 | ); 35 | 36 | matrix = glm::translate(&matrix, &entity.position); 37 | 38 | matrix 39 | } 40 | 41 | pub fn make_view_matrix(camera: &Camera) -> glm::TMat4 { 42 | let mut matrix = glm::diagonal4x4( 43 | &glm::vec4(1.0f32, 1.0, 1.0, 1.0) 44 | ); 45 | 46 | matrix = glm::rotate( 47 | &matrix, camera.rotation.x.to_radians(), &glm::vec3(1.0, 0.0, 0.0) 48 | ); 49 | matrix = glm::rotate( 50 | &matrix, camera.rotation.y.to_radians(), &glm::vec3(0.0, 1.0, 0.0) 51 | ); 52 | matrix = glm::rotate( 53 | &matrix, camera.rotation.z.to_radians(), &glm::vec3(1.0, 0.0, 1.0) 54 | ); 55 | 56 | matrix = glm::translate(&matrix, &(-camera.position)); 57 | 58 | matrix 59 | } 60 | 61 | pub fn make_projection_matrix(config: &Config) -> glm::TMat4 { 62 | let x = config.window_x as f32; 63 | let y = config.window_y as f32; 64 | let fov = config.fov as f32; 65 | 66 | glm::perspective(fov.to_radians(), x / y, 0.1, 2000.0) 67 | } -------------------------------------------------------------------------------- /src/maths/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod vector2xz; 18 | pub mod frustum; 19 | pub mod general_maths; 20 | pub mod matrix; 21 | pub mod noise_generator; 22 | pub mod ray; -------------------------------------------------------------------------------- /src/maths/noise_generator.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::num::Wrapping; 18 | use crate::world::world_constants::{CHUNK_SIZE, WATER_LEVEL}; 19 | 20 | #[derive(Copy, Clone, Default)] 21 | pub struct NoiseParameters { 22 | pub octaves: i32, 23 | pub amplitude: i32, 24 | pub smoothness: i32, 25 | pub height_offset: i32, 26 | 27 | pub roughness: f64 28 | } 29 | 30 | /// @brief Perlin noise generator used in construction of chunks and chunk blocks. 31 | pub struct NoiseGenerator { 32 | noise_parameters: NoiseParameters, 33 | seed: i32 34 | } 35 | 36 | impl NoiseParameters { 37 | pub fn new( 38 | octaves: i32, 39 | amplitude: i32, 40 | smoothness: i32, 41 | height_offset: i32, 42 | roughness: f64 43 | ) -> Self { 44 | Self { octaves, amplitude, smoothness, height_offset, roughness } 45 | } 46 | } 47 | 48 | impl NoiseGenerator { 49 | pub fn new(seed: i32) -> Self { 50 | let mut result = Self { 51 | noise_parameters: Default::default(), 52 | seed 53 | }; 54 | 55 | result.noise_parameters.octaves = 7; 56 | result.noise_parameters.amplitude = 70; 57 | result.noise_parameters.smoothness = 235; 58 | result.noise_parameters.height_offset = -5; 59 | result.noise_parameters.roughness = 0.53; 60 | 61 | result 62 | } 63 | 64 | /// @brief Gets the height of the chunk for the sake of Noise Generation. 65 | /// @param x 66 | /// @param z 67 | /// @param chunkX 68 | /// @param chunkZ 69 | /// @return val 70 | pub fn get_height(&self, x: i32, z: i32, chunk_x: i32, chunk_z: i32) -> f64 { 71 | let new_x = x.wrapping_add(chunk_x.wrapping_mul(CHUNK_SIZE as i32)); 72 | let new_z = z.wrapping_add(chunk_z.wrapping_mul(CHUNK_SIZE as i32)); 73 | 74 | if new_x < 0 || new_z < 0 { 75 | return WATER_LEVEL as f64 - 1.0; 76 | } 77 | 78 | let mut total_value = 0f64; 79 | 80 | // This loops through the octaves. 81 | for a in 0..self.noise_parameters.octaves - 1 { 82 | // This increases the frequency with every loop of the octave. 83 | let frequency = 2f64.powi(a); 84 | // This decreases the amplitude with every loop of the octave. 85 | let amplitude = self.noise_parameters.roughness.powi(a); 86 | total_value += self.noise( 87 | new_x as f64 * frequency / self.noise_parameters.smoothness as f64, 88 | new_z as f64 * frequency / self.noise_parameters.smoothness as f64 89 | ) * amplitude; 90 | } 91 | 92 | let val = (total_value / 2.1 + 1.2) * self.noise_parameters.amplitude as f64 93 | + self.noise_parameters.height_offset as f64; 94 | 95 | if val > 0.0 { val } else { 1.0 } // Compare if value is greater than 0 96 | } 97 | 98 | pub fn set_parameters(&mut self, params: NoiseParameters) { 99 | self.noise_parameters = params; 100 | } 101 | 102 | /// @brief Gets Noise through n which acts as a seed number. 103 | /// @param n 104 | /// @return 105 | fn get_noise_i(&self, n: i32) -> f64 { 106 | let mut n = Wrapping(n); 107 | n += self.seed; 108 | n = (n << 13) ^ n; 109 | let new_n = (n * (n * n * Wrapping(60493) + Wrapping(19990303)) + 110 | Wrapping(1376312589)) & Wrapping(0x7fffffff); 111 | 1.0 - new_n.0 as f64 / 1073741824.0 112 | } 113 | 114 | /// @brief Overload of getNoise that takes doubles instead of int n. 115 | /// @param x 116 | /// @param z 117 | /// @return 118 | fn get_noise_dd(&self, x: f64, z: f64) -> f64 { 119 | self.get_noise_i((x + z * 57.0) as i32) 120 | } 121 | 122 | fn lerp(a: f64, b: f64, z: f64) -> f64 { 123 | let mu2 = (1.0 - (z * 3.14).cos()) / 2.0; 124 | a * (1.0 - mu2) + b * mu2 125 | } 126 | 127 | fn noise(&self, x: f64, z: f64) -> f64 { 128 | let floor_x = x.floor(); 129 | let floor_z = z.floor(); 130 | 131 | let s = self.get_noise_dd(floor_x, floor_z); 132 | let t = self.get_noise_dd(floor_x + 1.0, floor_z); 133 | // Get the surrounding values to calculate the transition. 134 | let u = self.get_noise_dd(floor_x, floor_z + 1.0); 135 | let v = self.get_noise_dd(floor_x + 1.0, floor_z + 1.0); 136 | 137 | // Interpolate between the values. 138 | let rec1 = Self::lerp(s, t, x - floor_x); 139 | let rec2 = Self::lerp( 140 | u, v, 141 | x - floor_x // Here we use x-floorX, to get 1st dimension. Don't mind 142 | ); // the x-floorX thingie, it's part of the cosine formula. 143 | // Here we use y-floorZ, to get the 2nd dimension. 144 | let rec3 = Self::lerp(rec1, rec2, z - floor_z); 145 | 146 | rec3 147 | } 148 | } -------------------------------------------------------------------------------- /src/maths/ray.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | extern crate nalgebra_glm as glm; 18 | 19 | /// @brief Raycasting class associated with player's line of sight. 20 | pub struct Ray { 21 | ray_start: glm::TVec3, 22 | ray_end: glm::TVec3, 23 | direction: glm::TVec3 24 | } 25 | 26 | impl Ray { 27 | pub fn new(position: &glm::TVec3, direction: &glm::TVec3) -> Self { 28 | Self { 29 | ray_start: *position, 30 | ray_end: *position, 31 | direction: *direction 32 | } 33 | } 34 | 35 | pub fn step(&mut self, scale: f32) { 36 | let yaw = (self.direction.y + 90.0).to_radians(); 37 | let pitch = self.direction.x.to_radians(); 38 | 39 | self.ray_end.x -= yaw.cos() * scale; 40 | self.ray_end.z -= yaw.sin() * scale; 41 | self.ray_end.y -= pitch.tan() * scale; 42 | } 43 | 44 | pub fn end(&self) -> glm::TVec3 { 45 | self.ray_end 46 | } 47 | 48 | pub fn length(&self) -> f32 { 49 | glm::distance(&self.ray_start, &self.ray_end) 50 | } 51 | } -------------------------------------------------------------------------------- /src/maths/vector2xz.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #[derive(Copy, Clone, Default, Hash, Ord, PartialOrd, Eq, PartialEq)] 18 | pub struct VectorXZ { 19 | pub x: i32, 20 | pub z: i32 21 | } 22 | 23 | impl VectorXZ { 24 | pub fn new(x: i32, z: i32) -> Self { 25 | Self { 26 | x, 27 | z 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/mesh.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use gl::types::{GLfloat, GLuint}; 18 | 19 | /// @brief Mesh struct used for the purpose of constructing block meshes. 20 | #[derive(Clone, Default)] 21 | pub struct Mesh { 22 | pub vertex_positions: Vec, 23 | pub texture_coords: Vec, 24 | pub indices: Vec 25 | } -------------------------------------------------------------------------------- /src/model.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::{mem, ptr}; 18 | use gl::types::{GLfloat, GLuint}; 19 | use crate::mesh::Mesh; 20 | use crate::renderer::render_info::RenderInfo; 21 | 22 | /// @brief Models using mesh data to spawn entities for the game world. 23 | #[derive(Clone, Default)] 24 | pub struct Model { 25 | render_info: RenderInfo, 26 | 27 | vbo_count: i32, 28 | buffers: Vec 29 | } 30 | 31 | impl Model { 32 | /// @brief Default constructor. 33 | /// @param mesh 34 | pub fn new(mesh: &Mesh) -> Self { 35 | let mut result = Self::default(); 36 | result.add_data(mesh); 37 | result 38 | } 39 | 40 | pub fn add_data(&mut self, mesh: &Mesh) { 41 | self.gen_vao(); 42 | 43 | self.add_vbo(3, &mesh.vertex_positions); 44 | self.add_vbo(2, &mesh.texture_coords); 45 | self.add_ebo(&mesh.indices); 46 | } 47 | 48 | /// @brief Deletes model data, used to free models from memory. 49 | pub fn delete_data(&mut self) { 50 | unsafe { 51 | if self.render_info.vao != 0 { 52 | gl::DeleteVertexArrays(1, &self.render_info.vao); 53 | } 54 | if self.buffers.len() > 0 { 55 | gl::DeleteBuffers(self.buffers.len() as _, self.buffers.as_ptr()); 56 | } 57 | } 58 | 59 | self.buffers.clear(); 60 | 61 | self.vbo_count = 0; 62 | self.render_info.reset(); 63 | } 64 | 65 | pub fn gen_vao(&mut self) { 66 | if self.render_info.vao != 0 { 67 | self.delete_data(); 68 | } 69 | 70 | unsafe { 71 | gl::GenVertexArrays(1, &mut self.render_info.vao); 72 | gl::BindVertexArray(self.render_info.vao); 73 | } 74 | } 75 | 76 | pub fn add_ebo(&mut self, indices: &Vec) { 77 | self.render_info.indices_count = indices.len() as _; 78 | let mut ebo: GLuint = 0; 79 | unsafe { 80 | gl::GenBuffers(1, &mut ebo); 81 | gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo); 82 | gl::BufferData( 83 | gl::ELEMENT_ARRAY_BUFFER, 84 | (indices.len() * mem::size_of::()) as _, 85 | indices.as_ptr() as _, 86 | gl::STATIC_DRAW 87 | ); 88 | } 89 | } 90 | 91 | pub fn add_vbo(&mut self, dimensions: i32, data: &Vec) { 92 | let mut vbo: GLuint = 0; 93 | unsafe { 94 | gl::GenBuffers(1, &mut vbo); 95 | gl::BindBuffer(gl::ARRAY_BUFFER, vbo); 96 | gl::BufferData( 97 | gl::ARRAY_BUFFER, 98 | (data.len() * mem::size_of::()) as _, 99 | data.as_ptr() as _, 100 | gl::STATIC_DRAW 101 | ); 102 | 103 | gl::VertexAttribPointer( 104 | self.vbo_count as _, 105 | dimensions, 106 | gl::FLOAT, 107 | gl::FALSE, 108 | 0, 109 | ptr::null() 110 | ); 111 | 112 | gl::EnableVertexAttribArray(self.vbo_count as _); 113 | self.vbo_count += 1; 114 | } 115 | 116 | self.buffers.push(vbo); 117 | } 118 | 119 | pub fn bind_vao(&self) { 120 | unsafe { 121 | gl::BindVertexArray(self.render_info.vao); 122 | } 123 | } 124 | 125 | pub fn get_indices_count(&self) -> i32 { 126 | self.render_info.indices_count as _ 127 | } 128 | 129 | pub fn get_render_info(&self) -> &RenderInfo { 130 | &self.render_info 131 | } 132 | } 133 | 134 | impl Drop for Model { 135 | fn drop(&mut self) { 136 | self.delete_data(); 137 | } 138 | } -------------------------------------------------------------------------------- /src/physics/aabb.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | extern crate nalgebra_glm as glm; 18 | 19 | /// @brief Collision detection class for 3D environment. 20 | #[derive(Copy, Clone, Default)] 21 | pub struct AABB { 22 | pub position: glm::TVec3, 23 | pub dimensions: glm::TVec3 24 | } 25 | 26 | impl AABB { 27 | pub fn new(dim: &glm::TVec3) -> Self { 28 | Self { 29 | position: Default::default(), 30 | dimensions: *dim 31 | } 32 | } 33 | 34 | pub fn update(&mut self, location: &glm::TVec3) { 35 | self.position = *location; 36 | } 37 | 38 | pub fn get_vn(&self, normal: glm::TVec3) -> glm::TVec3 { 39 | let mut res = self.position; 40 | 41 | if normal.x < 0.0 { 42 | res.x += self.dimensions.x; 43 | } 44 | if normal.y < 0.0 { 45 | res.y += self.dimensions.y; 46 | } 47 | if normal.z < 0.0 { 48 | res.z += self.dimensions.z; 49 | } 50 | 51 | res 52 | } 53 | 54 | pub fn get_vp(&self, normal: glm::TVec3) -> glm::TVec3 { 55 | let mut res = self.position; 56 | 57 | if normal.x > 0.0 { 58 | res.x += self.dimensions.x; 59 | } 60 | if normal.y > 0.0 { 61 | res.y += self.dimensions.y; 62 | } 63 | if normal.z > 0.0 { 64 | res.z += self.dimensions.z; 65 | } 66 | 67 | res 68 | } 69 | } -------------------------------------------------------------------------------- /src/physics/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod aabb; -------------------------------------------------------------------------------- /src/player/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod player; -------------------------------------------------------------------------------- /src/renderer/chunk_renderer.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::camera::Camera; 18 | use crate::gl::gl_functions; 19 | use crate::renderer::render_info::RenderInfo; 20 | use crate::shaders::chunk_shader::ChunkShader; 21 | use crate::world::block::block_database::BlockDatabase; 22 | use crate::world::chunk::chunk_mesh::ChunkMesh; 23 | 24 | /// @brief Block chunk renderer that helps display block data. 25 | #[derive(Default)] 26 | pub struct ChunkRenderer { 27 | chunks: Vec, 28 | 29 | shader: ChunkShader 30 | } 31 | 32 | impl ChunkRenderer { 33 | pub fn add(&mut self, mesh: &ChunkMesh) { 34 | self.chunks.push(*mesh.get_model().get_render_info()); 35 | } 36 | 37 | pub fn render(&mut self, camera: &Camera) { 38 | if self.chunks.is_empty() { 39 | return; 40 | } 41 | 42 | unsafe { 43 | gl::Disable(gl::BLEND); 44 | gl::Enable(gl::CULL_FACE); 45 | } 46 | 47 | self.shader.base.base.use_program(); 48 | BlockDatabase::get().texture_atlas.bind_texture(); 49 | 50 | self.shader.base.load_projection_view_matrix(&camera.get_projection_view_matrix()); 51 | 52 | for mesh in self.chunks.iter() { 53 | gl_functions::bind_vao(mesh.vao); 54 | gl_functions::draw_elements(mesh.indices_count as _); 55 | } 56 | 57 | self.chunks.clear(); 58 | } 59 | } -------------------------------------------------------------------------------- /src/renderer/flora_renderer.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::application; 18 | use crate::camera::Camera; 19 | use crate::gl::gl_functions; 20 | use crate::renderer::render_info::RenderInfo; 21 | use crate::shaders::flora_shader::FloraShader; 22 | use crate::world::chunk::chunk_mesh::ChunkMesh; 23 | 24 | /// @brief Renderer handling 'flora' based entities that are not true blocks. 25 | #[derive(Default)] 26 | pub struct FloraRenderer { 27 | chunks: Vec, 28 | 29 | shader: FloraShader 30 | } 31 | 32 | impl FloraRenderer { 33 | pub fn add(&mut self, mesh: &ChunkMesh) { 34 | self.chunks.push(*mesh.get_model().get_render_info()); 35 | } 36 | 37 | pub fn render(&mut self, camera: &Camera) { 38 | if self.chunks.is_empty() { 39 | return; 40 | } 41 | 42 | unsafe { 43 | gl::Disable(gl::BLEND); 44 | gl::Disable(gl::CULL_FACE); 45 | } 46 | self.shader.base.base.use_program(); 47 | 48 | self.shader.base.load_projection_view_matrix(&camera.get_projection_view_matrix()); 49 | unsafe { 50 | self.shader.load_time(application::TIME_ELAPSED); 51 | } 52 | 53 | for mesh in self.chunks.iter() { 54 | gl_functions::bind_vao(mesh.vao); 55 | gl_functions::draw_elements(mesh.indices_count as _); 56 | } 57 | 58 | self.chunks.clear(); 59 | } 60 | } -------------------------------------------------------------------------------- /src/renderer/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod render_master; 18 | pub mod render_info; 19 | pub mod chunk_renderer; 20 | pub mod flora_renderer; 21 | pub mod skybox_renderer; 22 | pub mod water_renderer; -------------------------------------------------------------------------------- /src/renderer/render_info.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use gl::types::GLuint; 18 | 19 | #[derive(Copy, Clone, Default)] 20 | pub struct RenderInfo { 21 | pub vao: GLuint, 22 | pub indices_count: GLuint 23 | } 24 | 25 | impl RenderInfo { 26 | pub fn reset(&mut self) { 27 | self.vao = 0; 28 | self.indices_count = 0; 29 | } 30 | } -------------------------------------------------------------------------------- /src/renderer/render_master.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use sfml::window::Window; 18 | use crate::camera::Camera; 19 | use crate::renderer::chunk_renderer::ChunkRenderer; 20 | use crate::renderer::flora_renderer::FloraRenderer; 21 | use crate::renderer::skybox_renderer::SkyboxRenderer; 22 | use crate::renderer::water_renderer::WaterRenderer; 23 | use crate::world::chunk::chunk_section::ChunkSection; 24 | 25 | /// @brief Master rendering class that handles the sum of drawn in-game objects. 26 | #[derive(Default)] 27 | pub struct RenderMaster { 28 | // Chunks 29 | chunk_renderer: ChunkRenderer, 30 | water_renderer: WaterRenderer, 31 | flora_renderer: FloraRenderer, 32 | 33 | // Detail 34 | skybox_renderer: SkyboxRenderer, 35 | 36 | draw_box: bool 37 | } 38 | 39 | impl RenderMaster { 40 | pub fn draw_chunk(&mut self, chunk: &ChunkSection) { 41 | let solid_mesh = &chunk.get_meshes().solid_mesh; 42 | let water_mesh = &chunk.get_meshes().water_mesh; 43 | let flora_mesh = &chunk.get_meshes().flora_mesh; 44 | 45 | if solid_mesh.faces > 0 { 46 | self.chunk_renderer.add(solid_mesh); 47 | } 48 | 49 | if water_mesh.faces > 0 { 50 | self.water_renderer.add(water_mesh); 51 | } 52 | 53 | if flora_mesh.faces > 0 { 54 | self.flora_renderer.add(flora_mesh); 55 | } 56 | } 57 | 58 | pub fn draw_sky(&mut self) { 59 | self.draw_box = true; 60 | } 61 | 62 | pub fn finish_render(&mut self, window: &mut Window, camera: &Camera) { 63 | unsafe { 64 | gl::ClearColor(0.0, 0.0, 0.0, 1.0); 65 | gl::Clear(gl::DEPTH_BUFFER_BIT | gl::COLOR_BUFFER_BIT); 66 | 67 | gl::Enable(gl::DEPTH_TEST); 68 | gl::Enable(gl::CULL_FACE); 69 | } 70 | 71 | self.chunk_renderer.render(camera); 72 | self.water_renderer.render(camera); 73 | self.flora_renderer.render(camera); 74 | 75 | if self.draw_box { 76 | unsafe { 77 | gl::Disable(gl::CULL_FACE); 78 | } 79 | self.skybox_renderer.render(camera); 80 | self.draw_box = false; 81 | } 82 | 83 | window.display(); 84 | } 85 | } -------------------------------------------------------------------------------- /src/renderer/skybox_renderer.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use gl::types::{GLfloat, GLuint}; 18 | use crate::camera::Camera; 19 | use crate::gl::gl_functions; 20 | use crate::model::Model; 21 | use crate::shaders::skybox_shader::SkyboxShader; 22 | use crate::texture::cube_texture::CubeTexture; 23 | 24 | /// @brief Renderer that specifically draws the skybox and entities outside player reach. 25 | pub struct SkyboxRenderer { 26 | sky_cube: Model, 27 | shader: SkyboxShader, 28 | cube_texture: CubeTexture 29 | } 30 | 31 | impl SkyboxRenderer { 32 | pub fn render(&self, camera: &Camera) { 33 | self.shader.base.use_program(); 34 | self.sky_cube.bind_vao(); 35 | self.cube_texture.bind_texture(); 36 | 37 | self.shader.load_view_matrix(&camera.get_view_matrix()); 38 | self.shader.load_projection_matrix(&camera.get_proj_matrix()); 39 | 40 | gl_functions::draw_elements(self.sky_cube.get_indices_count()); 41 | } 42 | } 43 | 44 | impl Default for SkyboxRenderer { 45 | fn default() -> Self { 46 | let mut result = Self { 47 | sky_cube: Default::default(), 48 | shader: Default::default(), 49 | cube_texture: Default::default() 50 | }; 51 | 52 | const SIZE: GLfloat = 500.; 53 | let vertex_coords = vec![ 54 | // Back 55 | SIZE, 56 | -SIZE, 57 | -SIZE, 58 | -SIZE, 59 | -SIZE, 60 | -SIZE, 61 | -SIZE, 62 | SIZE, 63 | -SIZE, 64 | SIZE, 65 | SIZE, 66 | -SIZE, 67 | 68 | // Front 69 | -SIZE, 70 | -SIZE, 71 | SIZE, 72 | SIZE, 73 | -SIZE, 74 | SIZE, 75 | SIZE, 76 | SIZE, 77 | SIZE, 78 | -SIZE, 79 | SIZE, 80 | SIZE, 81 | 82 | // Right 83 | SIZE, 84 | -SIZE, 85 | SIZE, 86 | SIZE, 87 | -SIZE, 88 | -SIZE, 89 | SIZE, 90 | SIZE, 91 | -SIZE, 92 | SIZE, 93 | SIZE, 94 | SIZE, 95 | 96 | // Left 97 | -SIZE, 98 | -SIZE, 99 | -SIZE, 100 | -SIZE, 101 | -SIZE, 102 | SIZE, 103 | -SIZE, 104 | SIZE, 105 | SIZE, 106 | -SIZE, 107 | SIZE, 108 | -SIZE, 109 | 110 | // Top 111 | -SIZE, 112 | SIZE, 113 | SIZE, 114 | SIZE, 115 | SIZE, 116 | SIZE, 117 | SIZE, 118 | SIZE, 119 | -SIZE, 120 | -SIZE, 121 | SIZE, 122 | -SIZE, 123 | 124 | // Bottom 125 | -SIZE, 126 | -SIZE, 127 | -SIZE, 128 | SIZE, 129 | -SIZE, 130 | -SIZE, 131 | SIZE, 132 | -SIZE, 133 | SIZE, 134 | -SIZE, 135 | -SIZE, 136 | SIZE, 137 | ]; 138 | 139 | let indices: Vec = vec![ 140 | 0, 1, 2, 2, 3, 0, 141 | 142 | 4, 5, 6, 6, 7, 4, 143 | 144 | 8, 9, 10, 10, 11, 8, 145 | 146 | 12, 13, 14, 14, 15, 12, 147 | 148 | 16, 17, 18, 18, 19, 16, 149 | 150 | 20, 21, 22, 22, 23, 20 151 | ]; 152 | 153 | result.sky_cube.gen_vao(); 154 | result.sky_cube.add_vbo(3, &vertex_coords); 155 | result.sky_cube.add_ebo(&indices); 156 | 157 | result.cube_texture.load_from_files([ 158 | "dm", 159 | "dm", 160 | "dt", 161 | "db", 162 | "dm", 163 | "dm", 164 | ]); 165 | 166 | result 167 | } 168 | } -------------------------------------------------------------------------------- /src/renderer/water_renderer.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::application; 18 | use crate::camera::Camera; 19 | use crate::gl::gl_functions; 20 | use crate::renderer::render_info::RenderInfo; 21 | use crate::shaders::water_shader::WaterShader; 22 | use crate::world::chunk::chunk_mesh::ChunkMesh; 23 | 24 | /// @brief Renderer specifically targeting water and handling shader behaviors. 25 | #[derive(Default)] 26 | pub struct WaterRenderer { 27 | chunks: Vec, 28 | 29 | shader: WaterShader 30 | } 31 | 32 | impl WaterRenderer { 33 | pub fn add(&mut self, mesh: &ChunkMesh) { 34 | self.chunks.push(*mesh.get_model().get_render_info()); 35 | } 36 | 37 | pub fn render(&mut self, camera: &Camera) { 38 | if self.chunks.is_empty() { 39 | return; 40 | } 41 | 42 | unsafe { 43 | gl::Enable(gl::BLEND); 44 | gl::Disable(gl::CULL_FACE); 45 | } 46 | self.shader.base.base.use_program(); 47 | 48 | self.shader.base.load_projection_view_matrix(&camera.get_projection_view_matrix()); 49 | unsafe { 50 | self.shader.load_time(application::TIME_ELAPSED); 51 | } 52 | 53 | for mesh in self.chunks.iter() { 54 | gl_functions::bind_vao(mesh.vao); 55 | gl_functions::draw_elements(mesh.indices_count as _); 56 | } 57 | 58 | self.chunks.clear(); 59 | } 60 | } -------------------------------------------------------------------------------- /src/shaders/basic_shader.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | extern crate nalgebra_glm as glm; 18 | 19 | use std::ffi::CString; 20 | use gl::types::GLint; 21 | use crate::shaders::shader::{Shader, ShaderBase}; 22 | 23 | pub struct BasicShader { 24 | pub base: ShaderBase, 25 | 26 | location_projection_view_matrix: GLint, 27 | location_model_matrix: GLint 28 | } 29 | 30 | impl BasicShader { 31 | pub fn new(vertex_file: &str, fragment_file: &str) -> Self { 32 | Self { 33 | base: ShaderBase::new(vertex_file, fragment_file), 34 | location_projection_view_matrix: 0, 35 | location_model_matrix: 0 36 | } 37 | } 38 | 39 | pub fn load_projection_view_matrix(&self, pv_matrix: &glm::TMat4) { 40 | ShaderBase::load_matrix_4(self.location_projection_view_matrix, pv_matrix); 41 | } 42 | 43 | pub fn load_model_matrix(&self, matrix: &glm::TMat4) { 44 | ShaderBase::load_matrix_4(self.location_model_matrix, matrix); 45 | } 46 | } 47 | 48 | impl Default for BasicShader { 49 | fn default() -> Self { 50 | Self { 51 | base: ShaderBase::new("Basic", "Basic"), 52 | location_projection_view_matrix: 0, 53 | location_model_matrix: 0 54 | } 55 | } 56 | } 57 | 58 | impl Shader for BasicShader { 59 | fn get_uniforms(&mut self) { 60 | self.base.use_program(); 61 | unsafe { 62 | let c_string = CString::new("projViewMatrix").unwrap(); 63 | self.location_projection_view_matrix = gl::GetUniformLocation( 64 | self.base.id, c_string.as_ptr() 65 | ); 66 | let c_string = CString::new("modelMatrix").unwrap(); 67 | self.location_model_matrix = gl::GetUniformLocation( 68 | self.base.id, c_string.as_ptr() 69 | ); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /src/shaders/chunk_shader.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::shaders::basic_shader::BasicShader; 18 | use crate::shaders::shader::Shader; 19 | 20 | pub struct ChunkShader { 21 | pub base: BasicShader 22 | } 23 | 24 | impl Default for ChunkShader { 25 | fn default() -> Self { 26 | let mut result = Self { 27 | base: BasicShader::new("Chunk", "Chunk") 28 | }; 29 | result.get_uniforms(); 30 | result 31 | } 32 | } 33 | 34 | impl Shader for ChunkShader { 35 | fn get_uniforms(&mut self) { 36 | self.base.get_uniforms(); 37 | } 38 | } -------------------------------------------------------------------------------- /src/shaders/flora_shader.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::ffi::CString; 18 | use gl::types::GLint; 19 | use crate::shaders::basic_shader::BasicShader; 20 | use crate::shaders::shader::{Shader, ShaderBase}; 21 | 22 | pub struct FloraShader { 23 | pub base: BasicShader, 24 | 25 | time: GLint 26 | } 27 | 28 | impl FloraShader { 29 | pub fn load_time(&self, time: f32) { 30 | ShaderBase::load_float(self.time, time); 31 | } 32 | } 33 | 34 | impl Default for FloraShader { 35 | fn default() -> Self { 36 | let mut result = Self { 37 | base: BasicShader::new("Flora", "Chunk"), 38 | time: 0 39 | }; 40 | result.get_uniforms(); 41 | result 42 | } 43 | } 44 | 45 | impl Shader for FloraShader { 46 | fn get_uniforms(&mut self) { 47 | self.base.get_uniforms(); 48 | unsafe { 49 | let c_string = CString::new("globalTime").unwrap(); 50 | self.time = gl::GetUniformLocation(self.base.base.id, c_string.as_ptr()); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/shaders/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod shader; 18 | pub mod basic_shader; 19 | pub mod shader_loader; 20 | pub mod chunk_shader; 21 | pub mod flora_shader; 22 | pub mod water_shader; 23 | pub mod skybox_shader; -------------------------------------------------------------------------------- /src/shaders/shader.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | extern crate nalgebra_glm as glm; 18 | 19 | use gl::types::{GLint, GLuint}; 20 | use crate::shaders::shader_loader::load_shaders; 21 | 22 | pub trait Shader { 23 | fn get_uniforms(&mut self); 24 | } 25 | 26 | pub struct ShaderBase { 27 | pub id: GLuint 28 | } 29 | 30 | impl ShaderBase { 31 | pub fn new(vertex_file: &str, fragment_file: &str) -> Self { 32 | let result = Self { 33 | id: load_shaders(vertex_file, fragment_file) 34 | }; 35 | result.use_program(); 36 | result 37 | } 38 | 39 | pub fn load_int(location: GLint, value: i32) { 40 | unsafe { 41 | gl::Uniform1i(location, value); 42 | } 43 | } 44 | 45 | pub fn load_float(location: GLint, value: f32) { 46 | unsafe { 47 | gl::Uniform1f(location, value); 48 | } 49 | } 50 | 51 | pub fn load_vector_2(location: GLint, vect: &glm::TVec2) { 52 | unsafe { 53 | gl::Uniform2f(location, vect.x, vect.y); 54 | } 55 | } 56 | 57 | pub fn load_vector_3(location: GLint, vect: &glm::TVec3) { 58 | unsafe { 59 | gl::Uniform3f(location, vect.x, vect.y, vect.z); 60 | } 61 | } 62 | 63 | pub fn load_vector_4(location: GLint, vect: &glm::TVec4) { 64 | unsafe { 65 | gl::Uniform4f(location, vect.x, vect.y, vect.z, vect.w); 66 | } 67 | } 68 | 69 | pub fn load_matrix_4(location: GLint, matrix: &glm::TMat4) { 70 | unsafe { 71 | gl::UniformMatrix4fv(location, 1, gl::FALSE, &glm::value_ptr(matrix)[0]); 72 | } 73 | } 74 | 75 | pub fn use_program(&self) { 76 | unsafe { 77 | gl::UseProgram(self.id); 78 | } 79 | } 80 | } 81 | 82 | impl Drop for ShaderBase { 83 | fn drop(&mut self) { 84 | unsafe { 85 | gl::DeleteProgram(self.id); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /src/shaders/shader_loader.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::ffi::CString; 18 | use std::ptr; 19 | use gl::types::{GLchar, GLenum, GLint, GLuint}; 20 | use crate::util::file_util::get_file_contents; 21 | 22 | fn compile_shader(source: *const GLchar, shader_type: GLenum) -> Result { 23 | let shader_id; 24 | 25 | unsafe { 26 | shader_id = gl::CreateShader(shader_type); 27 | 28 | gl::ShaderSource(shader_id, 1, &source, ptr::null()); 29 | gl::CompileShader(shader_id); 30 | 31 | let mut is_success: GLint = 0; 32 | let mut info_log: [GLchar; 512] = [0; 512]; 33 | 34 | gl::GetShaderiv(shader_id, gl::COMPILE_STATUS, &mut is_success); 35 | if is_success == 0 { 36 | gl::GetShaderInfoLog( 37 | shader_id, 38 | 512, 39 | ptr::null_mut(), 40 | ptr::addr_of_mut!(info_log) as _ 41 | ); 42 | let info_log: Vec<_> = info_log.iter().map(|c| *c as u8).collect(); 43 | return Err(format!( 44 | "Unable to load a shader: {}", 45 | CString::new(info_log).unwrap().into_string().unwrap() 46 | )); 47 | } 48 | } 49 | 50 | Ok(shader_id) 51 | } 52 | 53 | fn link_program(vertex_shader_id: GLuint, fragment_shader_id: GLuint) -> GLuint { 54 | let id; 55 | 56 | unsafe { 57 | id = gl::CreateProgram(); 58 | 59 | gl::AttachShader(id, vertex_shader_id); 60 | gl::AttachShader(id, fragment_shader_id); 61 | 62 | gl::LinkProgram(id); 63 | } 64 | 65 | id 66 | } 67 | 68 | pub fn load_shaders(vertex_shader: &str, fragment_shader: &str) -> GLuint { 69 | let vertex_source = get_file_contents( 70 | format!("Shaders/{}.vert", vertex_shader).as_str() 71 | ); 72 | let fragment_source = get_file_contents( 73 | format!("Shaders/{}.frag", fragment_shader).as_str() 74 | ); 75 | 76 | let vertex_source = CString::new(vertex_source).unwrap(); 77 | let fragment_source = CString::new(fragment_source).unwrap(); 78 | 79 | let vertex_shader_id = compile_shader( 80 | vertex_source.as_ptr(), 81 | gl::VERTEX_SHADER 82 | ).unwrap(); 83 | let fragment_shader_id = compile_shader( 84 | fragment_source.as_ptr(), 85 | gl::FRAGMENT_SHADER 86 | ).unwrap(); 87 | 88 | let shader_id = link_program(vertex_shader_id, fragment_shader_id); 89 | 90 | unsafe { 91 | gl::DeleteShader(vertex_shader_id); 92 | gl::DeleteShader(fragment_shader_id); 93 | } 94 | 95 | shader_id 96 | } -------------------------------------------------------------------------------- /src/shaders/skybox_shader.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | extern crate nalgebra_glm as glm; 18 | 19 | use std::ffi::CString; 20 | use gl::types::GLint; 21 | use crate::shaders::shader::{Shader, ShaderBase}; 22 | 23 | pub struct SkyboxShader { 24 | pub base: ShaderBase, 25 | 26 | location_projection: GLint, 27 | location_view: GLint 28 | } 29 | 30 | impl SkyboxShader { 31 | pub fn new(vertex_file: &str, fragment_file: &str) -> Self { 32 | Self { 33 | base: ShaderBase::new(vertex_file, fragment_file), 34 | location_projection: 0, 35 | location_view: 0 36 | } 37 | } 38 | 39 | pub fn load_view_matrix(&self, view_matrix: &glm::TMat4) { 40 | let mut view_matrix = *view_matrix; 41 | view_matrix[(0, 3)] = 0.; 42 | view_matrix[(1, 3)] = 0.; 43 | view_matrix[(2, 3)] = 0.; 44 | ShaderBase::load_matrix_4(self.location_view, &view_matrix); 45 | } 46 | 47 | pub fn load_projection_matrix(&self, proj: &glm::TMat4) { 48 | ShaderBase::load_matrix_4(self.location_projection, proj); 49 | } 50 | } 51 | 52 | impl Default for SkyboxShader { 53 | fn default() -> Self { 54 | Self { 55 | base: ShaderBase::new("Skybox", "Skybox"), 56 | location_projection: 0, 57 | location_view: 0 58 | } 59 | } 60 | } 61 | 62 | impl Shader for SkyboxShader { 63 | fn get_uniforms(&mut self) { 64 | unsafe { 65 | let c_string = CString::new("projectionMatrix").unwrap(); 66 | self.location_projection = gl::GetUniformLocation(self.base.id, c_string.as_ptr()); 67 | let c_string = CString::new("viewMatrix").unwrap(); 68 | self.location_view = gl::GetUniformLocation(self.base.id, c_string.as_ptr()); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /src/shaders/water_shader.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::ffi::CString; 18 | use gl::types::GLint; 19 | use crate::shaders::basic_shader::BasicShader; 20 | use crate::shaders::shader::{Shader, ShaderBase}; 21 | 22 | pub struct WaterShader { 23 | pub base: BasicShader, 24 | 25 | time: GLint 26 | } 27 | 28 | impl WaterShader { 29 | pub fn load_time(&self, time: f32) { 30 | ShaderBase::load_float(self.time, time); 31 | } 32 | } 33 | 34 | impl Default for WaterShader { 35 | fn default() -> Self { 36 | let mut result = Self { 37 | base: BasicShader::new("Water", "Chunk"), 38 | time: 0 39 | }; 40 | result.get_uniforms(); 41 | result 42 | } 43 | } 44 | 45 | impl Shader for WaterShader { 46 | fn get_uniforms(&mut self) { 47 | self.base.get_uniforms(); 48 | unsafe { 49 | let c_string = CString::new("globalTime").unwrap(); 50 | self.time = gl::GetUniformLocation(self.base.base.id, c_string.as_ptr()); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/states/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod state_base; 18 | pub mod play_state; -------------------------------------------------------------------------------- /src/states/play_state.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | extern crate nalgebra_glm as glm; 18 | 19 | use std::cell::UnsafeCell; 20 | use std::ptr; 21 | use std::rc::Rc; 22 | use std::sync::Arc; 23 | use sfml::SfBox; 24 | use sfml::system::Clock; 25 | use sfml::window::{Event, Key}; 26 | use sfml::window::mouse::Button; 27 | use crate::application::Application; 28 | use crate::config::Config; 29 | use crate::input::keyboard::Keyboard; 30 | use crate::input::toggle_key::ToggleKey; 31 | use crate::maths::ray::Ray; 32 | use crate::player::player::Player; 33 | use crate::renderer::render_master::RenderMaster; 34 | use crate::states::state_base::StateBase; 35 | use crate::util::fps_counter::FPSCounter; 36 | use crate::util::unsafe_cell_wrapper::UnsafeCellWrapper; 37 | use crate::world::block::block_id::BlockId; 38 | use crate::world::event::player_dig_event::PlayerDigEvent; 39 | use crate::world::world::World; 40 | 41 | /// @brief Active game playing state, not associated with game menus. 42 | pub struct StatePlay<'a> { 43 | application: Rc>, 44 | 45 | keyboard: Keyboard, 46 | player: Player<'a>, 47 | world: Option>>, 48 | 49 | fps_counter: FPSCounter<'a> 50 | } 51 | 52 | static mut TIMER_PTR: *mut SfBox = ptr::null_mut(); 53 | 54 | static mut DT_PTR: *mut SfBox = ptr::null_mut(); 55 | static mut DRAW_GUI: bool = false; 56 | static mut DRAW_KEY_PTR: *mut ToggleKey = ptr::null_mut(); 57 | 58 | impl<'a> StatePlay<'a> { 59 | pub fn new_boxed(application: Rc>, config: Config) -> Box { 60 | let result = Self { 61 | application: Rc::clone(&application), 62 | keyboard: Keyboard::new(), 63 | player: Player::default(), 64 | world: None, 65 | fps_counter: FPSCounter::new() 66 | }; 67 | let mut result = Box::new(result); 68 | unsafe { 69 | result.world = Some(World::new( 70 | (*application.get()).camera(), 71 | &config, 72 | &mut result.player) 73 | ); 74 | 75 | (*(*application.get()).camera().get()).hook_entity(&result.player.base); 76 | } 77 | 78 | result 79 | } 80 | } 81 | 82 | impl<'a> StateBase for StatePlay<'a> { 83 | fn handle_event(&mut self, event: Event) { 84 | self.keyboard.update(event); 85 | } 86 | 87 | fn handle_input(&mut self) { 88 | unsafe { 89 | self.player.handle_input((*self.application.get()).window_mut(), &self.keyboard); 90 | } 91 | 92 | unsafe { 93 | if TIMER_PTR == ptr::null_mut() { 94 | let timer = Box::new(Clock::start()); 95 | TIMER_PTR = Box::leak(timer); 96 | } 97 | } 98 | let mut last_position: glm::TVec3 = Default::default(); 99 | 100 | // Ray is cast as player's 'vision' 101 | let mut ray = Ray::new( 102 | &glm::vec3( 103 | self.player.position.x, 104 | self.player.position.y + 0.6, 105 | self.player.position.z 106 | ), 107 | &self.player.rotation 108 | ); // Corrected for camera offset 109 | while ray.length() < 6. { 110 | let x = ray.end().x as i32; 111 | let y = ray.end().y as i32; 112 | let z = ray.end().z as i32; 113 | 114 | let block = unsafe { 115 | (*self.world.as_ref().unwrap().get()).get_block(x, y, z) 116 | }; 117 | let id = BlockId::try_from(block.id as i32).unwrap(); 118 | 119 | if id != BlockId::Air && id != BlockId::Water { 120 | unsafe { 121 | if (*TIMER_PTR).elapsed_time().as_seconds() > 0.2 { 122 | if Button::Left.is_pressed() { 123 | (*TIMER_PTR).restart(); 124 | // The player "digs" the block up 125 | (*self.world.as_ref().unwrap().get()).add_event(Box::new( 126 | PlayerDigEvent::new( 127 | Button::Left, 128 | ray.end(), 129 | &mut self.player 130 | ) 131 | )); 132 | break; 133 | } else if Button::Right.is_pressed() { 134 | (*TIMER_PTR).restart(); 135 | // The player "digs" the block up 136 | (*self.world.as_ref().unwrap().get()).add_event(Box::new( 137 | PlayerDigEvent::new( 138 | Button::Right, 139 | last_position, 140 | &mut self.player 141 | ) 142 | )); 143 | break; 144 | } 145 | } 146 | } 147 | } 148 | last_position = ray.end(); 149 | 150 | ray.step(0.05); 151 | } 152 | } 153 | 154 | fn update(&mut self, delta_time: f32) { 155 | if self.player.position.x < 0. { 156 | self.player.position.x = 0.; 157 | } 158 | if self.player.position.z < 0. { 159 | self.player.position.z = 0.; 160 | } 161 | 162 | self.fps_counter.update(); 163 | self.player.update( 164 | delta_time, 165 | unsafe { 166 | &mut *self.world.as_ref().unwrap().get() 167 | } 168 | ); 169 | unsafe { 170 | let arc = Arc::clone(&(*self.application.get()).camera()); 171 | let camera = &*arc.get(); 172 | World::update(&Arc::clone(self.world.as_ref().unwrap()), &camera); 173 | } 174 | } 175 | 176 | fn render(&mut self, renderer: &mut RenderMaster) { 177 | unsafe { 178 | if DT_PTR == ptr::null_mut() { 179 | let dt = Box::new(Clock::start()); 180 | DT_PTR = Box::leak(dt); 181 | } 182 | if DRAW_KEY_PTR == ptr::null_mut() { 183 | let draw_key = Box::new(ToggleKey::new(Key::F3)); 184 | DRAW_KEY_PTR = Box::leak(draw_key); 185 | } 186 | 187 | if (*DRAW_KEY_PTR).is_key_pressed() { 188 | DRAW_GUI = !DRAW_GUI; 189 | } 190 | 191 | if DRAW_GUI { 192 | self.fps_counter.draw(renderer); 193 | self.player.draw(renderer); 194 | } 195 | 196 | let arc = Arc::clone(&(*self.application.get()).camera()); 197 | let camera = &*arc.get(); 198 | (*self.world.as_ref().unwrap().get()).render_world(renderer, &camera); 199 | } 200 | } 201 | 202 | fn on_open(&mut self) { 203 | unsafe { 204 | (*self.application.get()).turn_off_mouse(); 205 | } 206 | } 207 | } -------------------------------------------------------------------------------- /src/states/state_base.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use sfml::window::Event; 18 | use crate::renderer::render_master::RenderMaster; 19 | 20 | pub trait StateBase { 21 | fn handle_event(&mut self, event: Event); 22 | fn handle_input(&mut self); 23 | fn update(&mut self, delta_time: f32); 24 | fn render(&mut self, renderer: &mut RenderMaster); 25 | fn on_open(&mut self); 26 | } -------------------------------------------------------------------------------- /src/texture/basic_texture.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use gl::types::GLuint; 18 | use sfml::graphics::Image; 19 | 20 | /// @brief Standard texture that will be mapped to objects. 21 | #[derive(Default)] 22 | pub struct BasicTexture { 23 | id: GLuint 24 | } 25 | 26 | impl BasicTexture { 27 | pub fn new(file: &str) -> Self { 28 | let mut result = Self::default(); 29 | result.load_from_file(file); 30 | result 31 | } 32 | 33 | pub fn load_from_image(&mut self, i: &Image) { 34 | unsafe { 35 | gl::GenTextures(1, &mut self.id); 36 | gl::ActiveTexture(gl::TEXTURE0); 37 | gl::BindTexture(gl::TEXTURE_2D, self.id); 38 | 39 | let pixel_data = i.pixel_data(); 40 | let pixel_data_vec = Vec::from(pixel_data); 41 | gl::TexImage2D( 42 | gl::TEXTURE_2D, 43 | 0, 44 | gl::RGBA as _, 45 | i.size().x as _, 46 | i.size().y as _, 47 | 0, 48 | gl::RGBA, 49 | gl::UNSIGNED_BYTE, 50 | pixel_data_vec.as_ptr() as _ 51 | ); 52 | 53 | gl::GenerateMipmap(gl::TEXTURE_2D); 54 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST_MIPMAP_NEAREST as _); 55 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as _); 56 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as _); 57 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as _); 58 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAX_LEVEL, 1); 59 | } 60 | } 61 | 62 | pub fn load_from_file(&mut self, file: &str) { 63 | let i = Image::from_file(format!("Res/Textures/{}.png", file).as_str()) 64 | .expect(format!("Unable to load BasicTexture: {}", file).as_str()); 65 | 66 | self.load_from_image(&i); 67 | } 68 | 69 | pub fn bind_texture(&self) { 70 | unsafe { 71 | gl::BindTexture(gl::TEXTURE_2D, self.id); 72 | } 73 | } 74 | } 75 | 76 | impl Drop for BasicTexture { 77 | fn drop(&mut self) { 78 | unsafe { 79 | gl::DeleteTextures(1, &self.id); 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /src/texture/cube_texture.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use gl::types::{GLenum, GLuint}; 18 | use sfml::graphics::Image; 19 | 20 | /// @brief Complex texture class that applies textures to all sides of a cube. 21 | #[derive(Default)] 22 | pub struct CubeTexture { 23 | tex_id: GLuint 24 | } 25 | 26 | impl CubeTexture { 27 | pub fn new(files: [&str; 6]) -> Self { 28 | let mut result = Self::default(); 29 | result.load_from_files(files); 30 | result 31 | } 32 | 33 | pub fn load_from_files(&mut self, files: [&str; 6]) { 34 | unsafe { 35 | gl::GenTextures(1, &mut self.tex_id); 36 | gl::ActiveTexture(gl::TEXTURE0); 37 | gl::BindTexture(gl::TEXTURE_CUBE_MAP, self.tex_id); 38 | 39 | for (i, s) in files.iter().enumerate() { 40 | let image = Image::from_file(format!("Res/Textures/{}.png", s).as_str()) 41 | .expect(format!("Unable to load CubeTexture Part: {}", s).as_str()); 42 | 43 | let param = gl::TEXTURE_CUBE_MAP_POSITIVE_X + i as GLenum; 44 | let width = image.size().x; 45 | let height = image.size().y; 46 | 47 | let pixel_data = image.pixel_data(); 48 | let pixel_data_vec = Vec::from(pixel_data); 49 | gl::TexImage2D( 50 | param, 51 | 0, 52 | gl::RGBA as _, 53 | width as _, 54 | height as _, 55 | 0, 56 | gl::RGBA, 57 | gl::UNSIGNED_BYTE, 58 | pixel_data_vec.as_ptr() as _ 59 | ); 60 | } 61 | 62 | gl::TexParameteri(gl::TEXTURE_CUBE_MAP, gl::TEXTURE_MIN_FILTER, gl::LINEAR as _); 63 | gl::TexParameteri(gl::TEXTURE_CUBE_MAP, gl::TEXTURE_MAG_FILTER, gl::LINEAR as _); 64 | 65 | gl::TexParameteri(gl::TEXTURE_CUBE_MAP, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as _); 66 | gl::TexParameteri(gl::TEXTURE_CUBE_MAP, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as _); 67 | } 68 | } 69 | 70 | pub fn bind_texture(&self) { 71 | unsafe { 72 | gl::BindTexture(gl::TEXTURE_CUBE_MAP, self.tex_id); 73 | } 74 | } 75 | } 76 | 77 | impl Drop for CubeTexture { 78 | fn drop(&mut self) { 79 | unsafe { 80 | gl::DeleteTextures(1, &self.tex_id); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /src/texture/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod texture_atlas; 18 | pub mod cube_texture; 19 | pub mod basic_texture; -------------------------------------------------------------------------------- /src/texture/texture_atlas.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use gl::types::{GLfloat, GLuint}; 18 | use sfml::graphics::Image; 19 | use sfml::system::Vector2i; 20 | 21 | /// @brief Texture atlas that pulls texture data from existing files and maps them appropraitely. 22 | #[derive(Default)] 23 | pub struct TextureAtlas { 24 | id: GLuint, 25 | image_size: i32, 26 | individual_texture_size: i32 27 | } 28 | 29 | const IMAGE_SIZE: i32 = 256; 30 | const INDIVIDUAL_TEXTURE_SIZE: i32 = 16; 31 | const TEX_PER_ROW: GLfloat = IMAGE_SIZE as GLfloat / INDIVIDUAL_TEXTURE_SIZE as GLfloat; 32 | const INDV_TEX_SIZE: GLfloat = 1f32 / TEX_PER_ROW; 33 | const PIXEL_SIZE: GLfloat = 1f32 / IMAGE_SIZE as f32; 34 | 35 | impl TextureAtlas { 36 | pub fn new(texture_file_name: &str) -> Self { 37 | let mut result = Self::default(); 38 | 39 | let i = Image::from_file(format!("Res/Textures/{}.png", texture_file_name).as_str()) 40 | .expect(format!("Unable to open image: {}", texture_file_name).as_str()); 41 | result.load_from_image(&i); 42 | 43 | result.image_size = IMAGE_SIZE; 44 | result.individual_texture_size = INDIVIDUAL_TEXTURE_SIZE; 45 | 46 | result 47 | } 48 | 49 | pub fn load_from_image(&mut self, image: &Image) { 50 | unsafe { 51 | gl::GenTextures(1, &mut self.id); 52 | gl::ActiveTexture(gl::TEXTURE0); 53 | gl::BindTexture(gl::TEXTURE_2D, self.id); 54 | 55 | let pixel_data = image.pixel_data(); 56 | let pixel_data_vec = Vec::from(pixel_data); 57 | gl::TexImage2D( 58 | gl::TEXTURE_2D, 59 | 0, 60 | gl::RGBA as _, 61 | image.size().x as _, 62 | image.size().y as _, 63 | 0, 64 | gl::RGBA, 65 | gl::UNSIGNED_BYTE, 66 | pixel_data_vec.as_ptr() as _ 67 | ); 68 | 69 | gl::GenerateMipmap(gl::TEXTURE_2D); 70 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST_MIPMAP_NEAREST as _); 71 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as _); 72 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as _); 73 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as _); 74 | gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAX_LEVEL, 1); 75 | } 76 | } 77 | 78 | pub fn load_from_file(&mut self, file: &str) { 79 | let i = Image::from_file(format!("Res/Textures/{}.png", file).as_str()) 80 | .expect(format!("Unable to load BasicTexture: {}", file).as_str()); 81 | self.load_from_image(&i); 82 | } 83 | 84 | pub fn bind_texture(&self) { 85 | unsafe { 86 | gl::BindTexture(gl::TEXTURE_2D, self.id); 87 | } 88 | } 89 | 90 | pub fn get_texture(&self, coords: &Vector2i) -> [GLfloat; 8] { 91 | let x_min = coords.x as f32 * INDV_TEX_SIZE + 0.5 * PIXEL_SIZE; 92 | let y_min = coords.y as f32 * INDV_TEX_SIZE + 0.5 * PIXEL_SIZE; 93 | 94 | let x_max = x_min + INDV_TEX_SIZE - PIXEL_SIZE; 95 | let y_max = y_min + INDV_TEX_SIZE - PIXEL_SIZE; 96 | 97 | [x_max, y_max, x_min, y_max, x_min, y_min, x_max, y_min] 98 | } 99 | } 100 | 101 | impl Drop for TextureAtlas { 102 | fn drop(&mut self) { 103 | unsafe { 104 | gl::DeleteTextures(1, &self.id); 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /src/util/array2d.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | /* 18 | TODO: There's some bug with the const generic parameters within Rust compiler. 19 | 20 | When adding `const WIDTH: usize` to the generic list, the following error occurs: 21 | 22 | error: unconstrained generic constant 23 | --> src/util/array2d.rs:3:12 24 | | 25 | 3 | array: [T; WIDTH * WIDTH] 26 | | ^^^^^^^^^^^^^^^^^^ 27 | | 28 | = help: try adding a `where` bound using this expression: `where [(); WIDTH * WIDTH]:` 29 | 30 | Hence the temporary solution is to switch the implementation to the version based on 31 | heap memory allocation, using Vec to simulate an "array". 32 | */ 33 | 34 | #[derive(Clone)] 35 | pub struct Array2D { 36 | array: Vec, 37 | width: usize 38 | } 39 | 40 | impl Array2D { 41 | pub fn new(width: usize) -> Self { 42 | let mut result = Self { 43 | array: Vec::with_capacity(width * width), 44 | width 45 | }; 46 | 47 | for _ in 0 .. width * width { 48 | result.array.push(T::default()); 49 | } 50 | 51 | result 52 | } 53 | } 54 | 55 | impl Array2D { 56 | pub fn get(&self, x: usize, z: usize) -> &T { 57 | &self.array[x * self.width + z] 58 | } 59 | 60 | pub fn get_mut(&mut self, x: usize, z: usize) -> &mut T { 61 | &mut self.array[x * self.width + z] 62 | } 63 | 64 | pub fn get_max_value(&self) -> &T { 65 | self.array.iter().max().unwrap() 66 | } 67 | 68 | pub fn set_all(&mut self, val: T) { 69 | self.array.fill(val) 70 | } 71 | 72 | pub fn width(&self) -> usize { 73 | self.width 74 | } 75 | } -------------------------------------------------------------------------------- /src/util/file_util.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::fs; 18 | 19 | pub fn get_file_contents(file_path: &str) -> String { 20 | fs::read_to_string(file_path).expect( 21 | format!("Unable to open file: {}", file_path).as_str()) 22 | } -------------------------------------------------------------------------------- /src/util/fps_counter.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use sfml::graphics::{Color, Font, Text, Transformable}; 18 | use sfml::SfBox; 19 | use sfml::system::{Clock, Vector2f}; 20 | use crate::renderer::render_master::RenderMaster; 21 | 22 | /// @brief Generally obsolete FPS counter associated with SFML. 23 | pub struct FPSCounter<'a> { 24 | enabled: bool, 25 | debugging: bool, 26 | 27 | text: Text<'a>, 28 | font: SfBox, 29 | 30 | delay_timer: SfBox, 31 | fps_timer: SfBox, 32 | 33 | fps: f32, 34 | 35 | frame_count: i32 36 | } 37 | 38 | impl<'a> FPSCounter<'a> { 39 | pub fn new() -> Self { 40 | let mut result = Self { 41 | enabled: true, 42 | debugging: false, 43 | text: Text::default(), 44 | font: Font::from_file("Res/Fonts/rs.ttf").unwrap(), 45 | delay_timer: Clock::start(), 46 | fps_timer: Clock::start(), 47 | fps: 0.0, 48 | frame_count: 0 49 | }; 50 | 51 | result.text.move_(Vector2f::new(10.0, 10.0)); 52 | result.text.set_outline_color(Color::BLACK); 53 | result.text.set_outline_thickness(2.0); 54 | 55 | result.text.set_character_size(25); 56 | 57 | result 58 | } 59 | 60 | pub fn init(&'a mut self) { 61 | self.text.set_font(&self.font); 62 | } 63 | 64 | pub fn update(&mut self) { 65 | self.frame_count += 1; 66 | if self.enabled { 67 | if self.delay_timer.elapsed_time().as_seconds() > 0.5 { 68 | self.fps = self.frame_count as f32 / self.fps_timer.restart().as_seconds(); 69 | self.frame_count = 0; 70 | self.delay_timer.restart(); 71 | 72 | // Only show this output in debug mode 73 | if self.debugging { 74 | log::debug!("{}", self.fps); 75 | } 76 | } 77 | } 78 | } 79 | 80 | pub fn draw(&mut self, _renderer: &RenderMaster) { 81 | self.text.set_string(format!("FPS: {}", self.fps).as_str()); 82 | } 83 | } -------------------------------------------------------------------------------- /src/util/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use nalgebra_glm::IVec3; 18 | use sfml::system::Vector3i; 19 | 20 | pub mod fps_counter; 21 | pub mod array2d; 22 | pub mod random; 23 | pub mod file_util; 24 | pub mod unsafe_cell_wrapper; 25 | 26 | pub fn ivec3_to_vector3i(ivec3: IVec3) -> Vector3i { 27 | Vector3i::new(ivec3.x, ivec3.y, ivec3.z) 28 | } 29 | 30 | pub fn vector3i_to_ivec3(vector3i: Vector3i) -> IVec3 { 31 | IVec3::new(vector3i.x, vector3i.y, vector3i.z) 32 | } -------------------------------------------------------------------------------- /src/util/random.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::sync::Mutex; 18 | use std::time::SystemTime; 19 | use lazy_static::lazy_static; 20 | use rand::distributions::uniform::{SampleRange, SampleUniform}; 21 | use rand::prelude::StdRng; 22 | use rand::Rng; 23 | use rand_core::SeedableRng; 24 | 25 | /// @brief Singleton class that increases randomness (such as with seeds) 26 | pub struct RandomSingleton { 27 | random_engine: Mutex 28 | } 29 | 30 | pub struct Random { 31 | random_engine: Mutex 32 | } 33 | 34 | lazy_static! { 35 | static ref INSTANCE: RandomSingleton = RandomSingleton::new(); 36 | } 37 | 38 | impl RandomSingleton { 39 | fn new() -> Self { 40 | let duration = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap(); 41 | Self { 42 | random_engine: Mutex::new(StdRng::seed_from_u64(duration.as_secs())) 43 | } 44 | } 45 | 46 | pub fn get() -> &'static Self { 47 | &INSTANCE 48 | } 49 | 50 | pub fn int_in_range(&self, range: impl SampleRange) -> T { 51 | self.random_engine.lock().unwrap().gen_range(range) 52 | } 53 | } 54 | 55 | impl Random { 56 | pub fn new() -> Self { 57 | Self::default() 58 | } 59 | 60 | pub fn new_with_seed(seed: u64) -> Self { 61 | Self { 62 | random_engine: Mutex::new(StdRng::seed_from_u64(seed)) 63 | } 64 | } 65 | 66 | pub fn set_seed(&mut self, seed: u64) { 67 | self.random_engine = Mutex::new(StdRng::seed_from_u64(seed)); 68 | } 69 | 70 | pub fn int_in_range(&self, range: impl SampleRange) -> T { 71 | self.random_engine.lock().unwrap().gen_range(range) 72 | } 73 | } 74 | 75 | impl Default for Random { 76 | fn default() -> Self { 77 | let duration = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap(); 78 | Self::new_with_seed(duration.as_secs()) 79 | } 80 | } -------------------------------------------------------------------------------- /src/util/unsafe_cell_wrapper.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::cell::UnsafeCell; 18 | use std::ops::{Deref, DerefMut}; 19 | 20 | pub struct UnsafeCellWrapper(UnsafeCell); 21 | 22 | impl UnsafeCellWrapper { 23 | pub fn new(field0: T) -> Self { 24 | Self(UnsafeCell::new(field0)) 25 | } 26 | } 27 | 28 | impl Deref for UnsafeCellWrapper { 29 | type Target = UnsafeCell; 30 | 31 | fn deref(&self) -> &Self::Target { 32 | &self.0 33 | } 34 | } 35 | 36 | impl DerefMut for UnsafeCellWrapper { 37 | fn deref_mut(&mut self) -> &mut Self::Target { 38 | &mut self.0 39 | } 40 | } 41 | 42 | unsafe impl Send for UnsafeCellWrapper {} 43 | 44 | unsafe impl Sync for UnsafeCellWrapper {} -------------------------------------------------------------------------------- /src/world/block/block_database.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::ptr; 18 | use std::sync::{Arc, RwLock}; 19 | use crate::texture::texture_atlas::TextureAtlas; 20 | use crate::world::block::block_data::BlockData; 21 | use crate::world::block::block_id::BlockId; 22 | use crate::world::block::block_types::block_type::{BlockType, DefaultBlock}; 23 | 24 | static mut INSTANCE_PTR: *mut BlockDatabase = ptr::null_mut(); 25 | 26 | /// @brief Singleton class that determines status and ID of blocks as a whole. 27 | pub struct BlockDatabase { 28 | pub texture_atlas: TextureAtlas, 29 | blocks: [Box; BlockId::NUM_TYPES] 30 | } 31 | 32 | impl BlockDatabase { 33 | fn new() -> Self { 34 | let texture_atlas = TextureAtlas::new("DefaultPack"); 35 | let blocks: [Box; 12] = [ 36 | Box::new(DefaultBlock::new("Air")), 37 | Box::new(DefaultBlock::new("Grass")), 38 | Box::new(DefaultBlock::new("Dirt")), 39 | Box::new(DefaultBlock::new("Stone")), 40 | Box::new(DefaultBlock::new("OakBark")), 41 | Box::new(DefaultBlock::new("OakLeaf")), 42 | Box::new(DefaultBlock::new("Sand")), 43 | Box::new(DefaultBlock::new("Water")), 44 | Box::new(DefaultBlock::new("Cactus")), 45 | Box::new(DefaultBlock::new("TallGrass")), 46 | Box::new(DefaultBlock::new("Rose")), 47 | Box::new(DefaultBlock::new("DeadShrub")) 48 | ]; 49 | Self { texture_atlas, blocks } 50 | } 51 | 52 | pub fn get() -> &'static Self { 53 | unsafe { 54 | if INSTANCE_PTR == ptr::null_mut() { 55 | // Allocate the instance on heap memory, 56 | // then leak it to get the raw pointer. 57 | let instance = Box::new(BlockDatabase::new()); 58 | INSTANCE_PTR = Box::leak(instance); 59 | } 60 | 61 | &*INSTANCE_PTR 62 | } 63 | } 64 | 65 | pub fn get_block(&self, id: BlockId) -> &dyn BlockType { 66 | self.blocks[id as usize].as_ref() 67 | } 68 | 69 | pub fn get_data(&self, id: BlockId) -> Arc> { 70 | self.blocks[id as usize].data() 71 | } 72 | } -------------------------------------------------------------------------------- /src/world/block/block_id.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub type BlockType = u8; 18 | 19 | /// @brief Known block ID types used in game. 20 | #[derive(Eq, PartialEq, Copy, Clone)] 21 | pub enum BlockId { 22 | Air = 0, 23 | Grass = 1, 24 | Dirt = 2, 25 | Stone = 3, 26 | OakBark = 4, 27 | OakLeaf = 5, 28 | Sand = 6, 29 | Water = 7, 30 | Cactus = 8, 31 | Rose = 9, 32 | TallGrass = 10, 33 | DeadShrub = 11 34 | } 35 | 36 | impl BlockId { 37 | pub const NUM_TYPES: usize = 12; 38 | } 39 | 40 | impl TryFrom for BlockId { 41 | type Error = (); 42 | 43 | fn try_from(value: i32) -> Result { 44 | match value { 45 | x if x == BlockId::Air as i32 => Ok(BlockId::Air), 46 | x if x == BlockId::Grass as i32 => Ok(BlockId::Grass), 47 | x if x == BlockId::Dirt as i32 => Ok(BlockId::Dirt), 48 | x if x == BlockId::Stone as i32 => Ok(BlockId::Stone), 49 | x if x == BlockId::OakBark as i32 => Ok(BlockId::OakBark), 50 | x if x == BlockId::OakLeaf as i32 => Ok(BlockId::OakLeaf), 51 | x if x == BlockId::Sand as i32 => Ok(BlockId::Sand), 52 | x if x == BlockId::Water as i32 => Ok(BlockId::Water), 53 | x if x == BlockId::Cactus as i32 => Ok(BlockId::Cactus), 54 | x if x == BlockId::Rose as i32 => Ok(BlockId::Rose), 55 | x if x == BlockId::TallGrass as i32 => Ok(BlockId::TallGrass), 56 | x if x == BlockId::DeadShrub as i32 => Ok(BlockId::DeadShrub), 57 | _ => Err(()) 58 | } 59 | } 60 | } 61 | 62 | impl Default for BlockId { 63 | fn default() -> Self { 64 | Self::Air 65 | } 66 | } -------------------------------------------------------------------------------- /src/world/block/block_types/block_type.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::sync::{Arc, RwLock}; 18 | use crate::world::block::block_data::BlockData; 19 | 20 | pub trait BlockType { 21 | fn data(&self) -> Arc>; 22 | } 23 | 24 | pub struct DefaultBlock { 25 | data: Arc> 26 | } 27 | 28 | impl DefaultBlock { 29 | pub fn new(file_name: &str) -> Self { 30 | Self { 31 | data: Arc::new(RwLock::new(BlockData::new(file_name))) 32 | } 33 | } 34 | } 35 | 36 | impl BlockType for DefaultBlock { 37 | fn data(&self) -> Arc> { 38 | Arc::clone(&self.data) 39 | } 40 | } -------------------------------------------------------------------------------- /src/world/block/block_types/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod block_type; -------------------------------------------------------------------------------- /src/world/block/chunk_block.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::sync::{Arc, RwLock}; 18 | use crate::world::block::block_data::BlockData; 19 | use crate::world::block::block_database::BlockDatabase; 20 | use crate::world::block::block_id::{BlockId, BlockType}; 21 | 22 | #[derive(Copy, Clone, Default)] 23 | pub struct ChunkBlock { 24 | pub id: BlockType 25 | } 26 | 27 | impl ChunkBlock { 28 | pub fn new_with_block_type(id: BlockType) -> Self { 29 | Self { id } 30 | } 31 | 32 | pub fn new_with_block_id(id: BlockId) -> Self { 33 | Self { id: id as BlockType } 34 | } 35 | 36 | pub fn get_data(&self) -> Arc> { 37 | BlockDatabase::get() 38 | .get_data(BlockId::try_from(self.id as i32).unwrap()) 39 | } 40 | } -------------------------------------------------------------------------------- /src/world/block/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod chunk_block; 18 | pub mod block_id; 19 | pub mod block_database; 20 | pub mod block_types; 21 | pub mod block_data; -------------------------------------------------------------------------------- /src/world/chunk/chunk.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::sync::Arc; 18 | use sfml::system::{Vector2i, Vector3i}; 19 | use crate::camera::Camera; 20 | use crate::renderer::render_master::RenderMaster; 21 | use crate::util::array2d::Array2D; 22 | use crate::util::unsafe_cell_wrapper::UnsafeCellWrapper; 23 | use crate::world::block::block_id::BlockId; 24 | use crate::world::block::chunk_block::ChunkBlock; 25 | use crate::world::chunk::chunk_section::ChunkSection; 26 | use crate::world::generation::terrain_generator::TerrainGenerator; 27 | use crate::world::world::World; 28 | use crate::world::world_constants::CHUNK_SIZE; 29 | 30 | pub trait IChunk { 31 | fn get_block(&self, x: i32, y: i32, z: i32) -> ChunkBlock; 32 | fn set_block(&mut self, x: i32, y: i32, z: i32, block: ChunkBlock); 33 | } 34 | 35 | /// @brief A chunk, in other words, a large arrangement of blocks. 36 | pub struct Chunk { 37 | chunks: Vec, 38 | highest_blocks: Array2D, 39 | location: Vector2i, 40 | 41 | p_world: Arc>, 42 | 43 | is_loaded: bool, 44 | 45 | error_section: ChunkSection 46 | } 47 | 48 | impl Chunk { 49 | pub fn new(world: Arc>, location: Vector2i) -> Self { 50 | let mut result = Self { 51 | chunks: Vec::new(), 52 | highest_blocks: Array2D::new(CHUNK_SIZE), 53 | location, 54 | p_world: Arc::clone(&world), 55 | is_loaded: false, 56 | error_section: ChunkSection::new(Vector3i::new(444, 444, 444), world) 57 | }; 58 | result.highest_blocks.set_all(0); 59 | result 60 | } 61 | 62 | pub fn make_mesh(&mut self, camera: &Camera) -> bool { 63 | for chunk in self.chunks.iter_mut() { 64 | if !chunk.has_mesh() && camera.get_frustum().is_box_in_frustum(chunk.aabb) { 65 | chunk.make_mesh(); 66 | return true; 67 | } 68 | } 69 | false 70 | } 71 | 72 | pub fn get_height_at(&self, x: i32, z: i32) -> i32 { 73 | *self.highest_blocks.get(x as _, z as _) 74 | } 75 | 76 | pub fn draw_chunks(&mut self, renderer: &mut RenderMaster, camera: &Camera) { 77 | for chunk in self.chunks.iter_mut() { 78 | if chunk.has_mesh() { 79 | if !chunk.has_buffered() { 80 | chunk.buffer_mesh(); 81 | } 82 | 83 | if camera.get_frustum().is_box_in_frustum(chunk.aabb) { 84 | renderer.draw_chunk(chunk); 85 | } 86 | } 87 | } 88 | } 89 | 90 | pub fn has_loaded(&self) -> bool { 91 | self.is_loaded 92 | } 93 | 94 | pub fn load(&mut self, generator: &mut dyn TerrainGenerator) { 95 | if self.has_loaded() { 96 | return; 97 | } 98 | 99 | generator.generate_terrain_for(self); 100 | self.is_loaded = true; 101 | } 102 | 103 | pub fn get_section(&self, index: i32) -> &ChunkSection { 104 | if index >= self.chunks.len() as i32 || index < 0 { 105 | &self.error_section 106 | } else { 107 | &self.chunks[index as usize] 108 | } 109 | } 110 | 111 | pub fn get_section_mut(&mut self, index: i32) -> &mut ChunkSection { 112 | if index >= self.chunks.len() as i32 || index < 0 { 113 | &mut self.error_section 114 | } else { 115 | &mut self.chunks[index as usize] 116 | } 117 | } 118 | 119 | pub fn get_location(&self) -> Vector2i { 120 | self.location 121 | } 122 | 123 | pub fn delete_meshes(&mut self) { 124 | for chunk in self.chunks.iter_mut() { 125 | chunk.delete_meshes(); 126 | } 127 | } 128 | 129 | fn add_section(&mut self) { 130 | let y = self.chunks.len(); 131 | self.chunks.push(ChunkSection::new( 132 | Vector3i::new(self.location.x, y as _, self.location.y), 133 | Arc::clone(&self.p_world) 134 | )); 135 | } 136 | 137 | fn add_sections_block_target(&mut self, block_y: i32) { 138 | let index = block_y / CHUNK_SIZE as i32; 139 | self.add_sections_index_target(index); 140 | } 141 | 142 | fn add_sections_index_target(&mut self, index: i32) { 143 | while (self.chunks.len() as i32) < index + 1 { 144 | self.add_section(); 145 | } 146 | } 147 | 148 | fn out_of_bound(&self, x: i32, y: i32, z: i32) -> bool { 149 | if x >= CHUNK_SIZE as i32 { 150 | return true; 151 | } 152 | if z >= CHUNK_SIZE as i32 { 153 | return true; 154 | } 155 | 156 | if x < 0 { 157 | return true; 158 | } 159 | if y < 0 { 160 | return true; 161 | } 162 | if z < 0 { 163 | return true; 164 | } 165 | 166 | if y >= (self.chunks.len() * CHUNK_SIZE) as i32 { 167 | return true; 168 | } 169 | 170 | false 171 | } 172 | } 173 | 174 | impl IChunk for Chunk { 175 | fn get_block(&self, x: i32, y: i32, z: i32) -> ChunkBlock { 176 | if self.out_of_bound(x, y, z) { 177 | return ChunkBlock::new_with_block_id(BlockId::Air); 178 | } 179 | 180 | let b_y = y % CHUNK_SIZE as i32; 181 | 182 | self.chunks[(y / CHUNK_SIZE as i32) as usize].get_block(x, b_y, z) 183 | } 184 | 185 | fn set_block(&mut self, x: i32, mut y: i32, z: i32, block: ChunkBlock) { 186 | self.add_sections_block_target(y); 187 | if self.out_of_bound(x, y, z) { 188 | return; 189 | } 190 | 191 | let b_y = y % CHUNK_SIZE as i32; 192 | self.chunks[(y / CHUNK_SIZE as i32) as usize].set_block(x, b_y, z, block); 193 | 194 | if y == *self.highest_blocks.get(x as _, z as _) { 195 | let mut high_block = self.get_block(x, y, z); 196 | y -= 1; 197 | while !high_block.get_data().read().unwrap().block_data().is_opaque { 198 | high_block = self.get_block(x, y, z); 199 | y -= 1; 200 | } 201 | } else if y > *self.highest_blocks.get(x as _, z as _) { 202 | *self.highest_blocks.get_mut(x as _, z as _) = y; 203 | } 204 | } 205 | } -------------------------------------------------------------------------------- /src/world/chunk/chunk_manager.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use std::collections::HashMap; 18 | use std::sync::Arc; 19 | use sfml::system::Vector2i; 20 | use crate::camera::Camera; 21 | use crate::maths::vector2xz::VectorXZ; 22 | use crate::util::unsafe_cell_wrapper::UnsafeCellWrapper; 23 | use crate::world::chunk::chunk::Chunk; 24 | use crate::world::generation::classic_over_world_generator::ClassicOverWorldGenerator; 25 | use crate::world::generation::terrain_generator::TerrainGenerator; 26 | use crate::world::world::World; 27 | 28 | pub type ChunkMap = HashMap; 29 | 30 | /// @brief Dynamic chunk manager that affects chunk and block placement. 31 | pub struct ChunkManager { 32 | chunks: ChunkMap, 33 | terrain_generator: Box, 34 | 35 | world: Arc> 36 | } 37 | 38 | impl ChunkManager { 39 | pub fn new(world: Arc>) -> Self { 40 | Self { 41 | chunks: HashMap::new(), 42 | terrain_generator: Box::new(ClassicOverWorldGenerator::new()), 43 | world 44 | } 45 | } 46 | 47 | pub fn get_chunk(&mut self, x: i32, z: i32) -> &Chunk { 48 | let key = VectorXZ::new(x, z); 49 | if !self.chunk_exists_at(x, z) { 50 | let chunk = Chunk::new(Arc::clone(&self.world), Vector2i::new(x, z)); 51 | self.chunks.insert(key, chunk); 52 | } 53 | 54 | self.chunks.get(&key).unwrap() 55 | } 56 | 57 | pub fn get_chunk_mut(&mut self, x: i32, z: i32) -> &mut Chunk { 58 | let key = VectorXZ::new(x, z); 59 | if !self.chunk_exists_at(x, z) { 60 | let chunk = Chunk::new(Arc::clone(&self.world), Vector2i::new(x, z)); 61 | self.chunks.insert(key, chunk); 62 | } 63 | 64 | self.chunks.get_mut(&key).unwrap() 65 | } 66 | 67 | pub fn get_chunks(&self) -> &ChunkMap { 68 | &self.chunks 69 | } 70 | 71 | pub fn get_chunks_mut(&mut self) -> &mut ChunkMap { 72 | &mut self.chunks 73 | } 74 | 75 | pub fn make_mesh(&mut self, x: i32, z: i32, camera: &Camera) -> bool { 76 | for nx in -1 ..= 1 { 77 | for nz in -1 ..= 1 { 78 | self.load_chunk(x + nx, z + nz); 79 | } 80 | } 81 | 82 | self.get_chunk_mut(x, z).make_mesh(camera) 83 | } 84 | 85 | pub fn chunk_loaded_at(&self, x: i32, z: i32) -> bool { 86 | if !self.chunk_exists_at(x, z) { 87 | return false; 88 | } 89 | 90 | self.chunks.get(&VectorXZ::new(x, z)).unwrap().has_loaded() 91 | } 92 | 93 | pub fn chunk_exists_at(&self, x: i32, z: i32) -> bool { 94 | match self.chunks.get(&VectorXZ::new(x, z)) { 95 | Some(_) => true, 96 | None => false 97 | } 98 | } 99 | 100 | pub fn load_chunk(&mut self, x: i32, z: i32) { 101 | let ptr = &mut self.terrain_generator as *mut Box; 102 | self.get_chunk_mut(x, z).load(unsafe { (*ptr).as_mut() }); 103 | } 104 | 105 | pub fn unload_chunk(&mut self, x: i32, z: i32) { 106 | //@TODO Save chunk to file ? 107 | if self.chunk_exists_at(x, z) { 108 | self.chunks.remove(&VectorXZ::new(x, z)); 109 | } 110 | } 111 | 112 | pub fn delete_meshes(&mut self) { 113 | for chunk in self.chunks.iter_mut() { 114 | chunk.1.delete_meshes(); 115 | } 116 | } 117 | 118 | pub fn get_terrain_generator(&self) -> &dyn TerrainGenerator { 119 | self.terrain_generator.as_ref() 120 | } 121 | } -------------------------------------------------------------------------------- /src/world/chunk/chunk_mesh.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use gl::types::{GLfloat, GLuint}; 18 | use sfml::system::Vector3i; 19 | use crate::mesh::Mesh; 20 | use crate::model::Model; 21 | use crate::world::world_constants::CHUNK_SIZE; 22 | 23 | #[derive(Clone, Default)] 24 | pub struct ChunkMesh { 25 | pub faces: i32, 26 | 27 | mesh: Mesh, 28 | model: Model, 29 | light: Vec, 30 | index_index: GLuint 31 | } 32 | 33 | #[derive(Clone, Default)] 34 | pub struct ChunkMeshCollection { 35 | pub solid_mesh: ChunkMesh, 36 | pub water_mesh: ChunkMesh, 37 | pub flora_mesh: ChunkMesh 38 | } 39 | 40 | impl ChunkMesh { 41 | pub fn add_face( 42 | &mut self, 43 | block_face: [GLfloat; 12], 44 | texture_coords: [GLfloat; 8], 45 | chunk_position: &Vector3i, 46 | block_position: &Vector3i, 47 | cardinal_light: GLfloat 48 | ) { 49 | self.faces += 1; 50 | let vertices = &mut self.mesh.vertex_positions; 51 | let tex_coords = &mut self.mesh.texture_coords; 52 | let indices = &mut self.mesh.indices; 53 | 54 | texture_coords.iter().for_each(|it| { 55 | tex_coords.push(*it); 56 | }); 57 | 58 | // Vertex: The current vertex in the "blockFace" vector, 4 vertex in total 59 | // hence "< 4" Index: X, Y, Z 60 | let mut index = 0; 61 | for _ in 0..4 { 62 | vertices.push(block_face[index] + (chunk_position.x * CHUNK_SIZE as i32 63 | + block_position.x) as f32); 64 | index += 1; 65 | vertices.push(block_face[index] + (chunk_position.y * CHUNK_SIZE as i32 66 | + block_position.y) as f32); 67 | index += 1; 68 | vertices.push(block_face[index] + (chunk_position.z * CHUNK_SIZE as i32 69 | + block_position.z) as f32); 70 | index += 1; 71 | self.light.push(cardinal_light); 72 | } 73 | 74 | indices.push(self.index_index); 75 | indices.push(self.index_index + 1); 76 | indices.push(self.index_index + 2); 77 | indices.push(self.index_index + 2); 78 | indices.push(self.index_index + 3); 79 | indices.push(self.index_index); 80 | self.index_index += 4; 81 | } 82 | 83 | pub fn buffer_mesh(&mut self) { 84 | self.model.add_data(&self.mesh); 85 | self.model.add_vbo(1, &self.light); 86 | 87 | self.mesh.vertex_positions.clear(); 88 | self.mesh.texture_coords.clear(); 89 | self.mesh.indices.clear(); 90 | self.light.clear(); 91 | 92 | self.mesh.vertex_positions.shrink_to_fit(); 93 | self.mesh.texture_coords.shrink_to_fit(); 94 | self.mesh.indices.shrink_to_fit(); 95 | self.light.shrink_to_fit(); 96 | 97 | self.index_index = 0; 98 | } 99 | 100 | pub fn get_model(&self) -> &Model { 101 | &self.model 102 | } 103 | 104 | pub fn delete_data(&mut self) { 105 | self.model.delete_data(); 106 | } 107 | } 108 | 109 | impl ChunkMeshCollection { 110 | pub fn new( 111 | solid_mesh: ChunkMesh, 112 | water_mesh: ChunkMesh, 113 | flora_mesh: ChunkMesh 114 | ) -> Self { 115 | Self { solid_mesh, water_mesh, flora_mesh } 116 | } 117 | } -------------------------------------------------------------------------------- /src/world/chunk/chunk_section.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | extern crate nalgebra_glm as glm; 18 | 19 | use std::slice::Iter; 20 | use std::sync::Arc; 21 | use sfml::system::Vector3i; 22 | use crate::physics::aabb::AABB; 23 | use crate::util::unsafe_cell_wrapper::UnsafeCellWrapper; 24 | use crate::world::block::chunk_block::ChunkBlock; 25 | use crate::world::chunk::chunk::IChunk; 26 | use crate::world::chunk::chunk_mesh::ChunkMeshCollection; 27 | use crate::world::chunk::chunk_mesh_builder::ChunkMeshBuilder; 28 | use crate::world::world::World; 29 | use crate::world::world_constants::{CHUNK_AREA, CHUNK_SIZE, CHUNK_VOLUME}; 30 | 31 | #[derive(Copy, Clone, Default)] 32 | pub struct Layer { 33 | solid_block_count: i32 34 | } 35 | 36 | pub struct ChunkSection { 37 | pub(crate) blocks: [ChunkBlock; CHUNK_VOLUME], 38 | layers: [Layer; CHUNK_SIZE], 39 | 40 | pub(crate) meshes: ChunkMeshCollection, 41 | pub aabb: AABB, 42 | pub(crate) location: Vector3i, 43 | 44 | p_world: Arc>, 45 | 46 | has_mesh: bool, 47 | has_buffered_mesh: bool 48 | } 49 | 50 | impl Layer { 51 | pub fn update(&mut self, c: ChunkBlock) { 52 | if c.get_data().read().unwrap().block_data().is_opaque { 53 | self.solid_block_count -= 1; 54 | } else { 55 | self.solid_block_count += 1; 56 | } 57 | } 58 | 59 | pub fn is_all_solid(&self) -> bool { 60 | self.solid_block_count == CHUNK_AREA as _ 61 | } 62 | } 63 | 64 | impl ChunkSection { 65 | pub fn new( 66 | location: Vector3i, 67 | world: Arc> 68 | ) -> Self { 69 | let mut result = Self { 70 | blocks: [ChunkBlock::default(); CHUNK_VOLUME], 71 | layers: Default::default(), 72 | meshes: Default::default(), 73 | aabb: AABB::new(&glm::vec3(CHUNK_SIZE as _, CHUNK_SIZE as _, CHUNK_SIZE as _)), 74 | location, 75 | p_world: world, 76 | has_mesh: false, 77 | has_buffered_mesh: false 78 | }; 79 | result.aabb.update(&glm::vec3( 80 | (location.x * CHUNK_SIZE as i32) as _, 81 | (location.y * CHUNK_SIZE as i32) as _, 82 | (location.z * CHUNK_SIZE as i32) as _ 83 | )); 84 | result 85 | } 86 | 87 | pub fn get_location(&self) -> Vector3i { 88 | self.location 89 | } 90 | 91 | pub fn has_mesh(&self) -> bool { 92 | self.has_mesh 93 | } 94 | 95 | pub fn has_buffered(&self) -> bool { 96 | self.has_buffered_mesh 97 | } 98 | 99 | pub fn make_mesh(&mut self) { 100 | ChunkMeshBuilder::new(self).build_mesh(); 101 | self.has_mesh = true; 102 | self.has_buffered_mesh = false; 103 | } 104 | 105 | pub fn buffer_mesh(&mut self) { 106 | self.meshes.solid_mesh.buffer_mesh(); 107 | self.meshes.water_mesh.buffer_mesh(); 108 | self.meshes.flora_mesh.buffer_mesh(); 109 | self.has_buffered_mesh = true; 110 | } 111 | 112 | pub fn exec_on_layer(&self, y: i32, func: impl FnOnce(&Layer) -> R) -> R { 113 | let p_world; 114 | unsafe { 115 | p_world = &mut *self.p_world.get(); 116 | } 117 | if y == -1 { 118 | p_world.get_chunk_manager_mut() 119 | .get_chunk(self.location.x, self.location.z) 120 | .get_section(self.location.y - 1) 121 | .exec_on_layer(CHUNK_SIZE as i32 - 1, func) 122 | } else if y == CHUNK_SIZE as i32 { 123 | p_world.get_chunk_manager_mut() 124 | .get_chunk(self.location.x, self.location.z) 125 | .get_section(self.location.y + 1) 126 | .exec_on_layer(0, func) 127 | } else { 128 | func(&self.layers[y as usize]) 129 | } 130 | } 131 | 132 | pub fn get_adjacent(&self, dx: i32, dz: i32) -> &ChunkSection { 133 | let new_x = self.location.x + dx; 134 | let new_z = self.location.z + dz; 135 | 136 | unsafe { 137 | (*self.p_world.get()).get_chunk_manager_mut() 138 | .get_chunk(new_x, new_z) 139 | .get_section(self.location.y) 140 | } 141 | } 142 | 143 | pub fn get_meshes(&self) -> &ChunkMeshCollection { 144 | &self.meshes 145 | } 146 | 147 | pub fn delete_meshes(&mut self) { 148 | if self.has_mesh { 149 | self.has_buffered_mesh = false; 150 | self.has_mesh = false; 151 | self.meshes.solid_mesh.delete_data(); 152 | self.meshes.water_mesh.delete_data(); 153 | self.meshes.flora_mesh.delete_data(); 154 | } 155 | } 156 | 157 | pub fn iter(&self) -> Iter<'_, ChunkBlock> { 158 | self.blocks.iter() 159 | } 160 | 161 | fn to_world_position(&self, x: i32, y: i32, z: i32) -> Vector3i { 162 | Vector3i::new( 163 | self.location.x * CHUNK_SIZE as i32 + x, 164 | self.location.y * CHUNK_SIZE as i32 + y, 165 | self.location.z * CHUNK_SIZE as i32 + z 166 | ) 167 | } 168 | 169 | fn out_of_bounds(value: i32) -> bool { 170 | value >= CHUNK_SIZE as i32 || value < 0 171 | } 172 | 173 | fn get_index(x: i32, y: i32, z: i32) -> i32 { 174 | y * CHUNK_AREA as i32 + z * CHUNK_SIZE as i32 + x 175 | } 176 | } 177 | 178 | impl IChunk for ChunkSection { 179 | fn get_block(&self, x: i32, y: i32, z: i32) -> ChunkBlock { 180 | if Self::out_of_bounds(x) || Self::out_of_bounds(y) || Self::out_of_bounds(z) { 181 | let location = self.to_world_position(x, y, z); 182 | unsafe { 183 | let p_world = &mut *self.p_world.get(); 184 | return p_world.get_block(location.x, location.y, location.z); 185 | } 186 | } 187 | 188 | self.blocks[Self::get_index(x, y, z) as usize] 189 | } 190 | 191 | fn set_block(&mut self, x: i32, y: i32, z: i32, block: ChunkBlock) { 192 | if Self::out_of_bounds(x) || Self::out_of_bounds(y) || Self::out_of_bounds(z) { 193 | let location = self.to_world_position(x, y, z); 194 | unsafe { 195 | let p_world = &mut *self.p_world.get(); 196 | p_world.set_block(location.x, location.y, location.z, block); 197 | } 198 | return; 199 | } 200 | 201 | self.layers[y as usize].update(block); 202 | 203 | self.blocks[Self::get_index(x, y, z) as usize] = block; 204 | } 205 | } -------------------------------------------------------------------------------- /src/world/chunk/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod chunk_manager; 18 | pub mod chunk; 19 | pub mod chunk_section; 20 | pub mod chunk_mesh; 21 | pub mod chunk_mesh_builder; -------------------------------------------------------------------------------- /src/world/event/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod world_event; 18 | pub mod player_dig_event; -------------------------------------------------------------------------------- /src/world/event/player_dig_event.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | extern crate nalgebra_glm as glm; 18 | 19 | use std::ffi::c_void; 20 | use sfml::window::mouse::Button; 21 | use crate::item::material::{ID, Material}; 22 | use crate::player::player::Player; 23 | use crate::world::block::block_id::BlockId; 24 | use crate::world::block::chunk_block::ChunkBlock; 25 | use crate::world::event::world_event::IWorldEvent; 26 | use crate::world::world::World; 27 | 28 | pub struct PtrMutPlayer(*mut c_void); 29 | 30 | /// @brief Event class that handles what happens to a block in a world as a player interacts. 31 | pub struct PlayerDigEvent { 32 | button_press: Button, 33 | dig_spot: glm::TVec3, 34 | p_player: PtrMutPlayer 35 | } 36 | 37 | impl PtrMutPlayer { 38 | pub fn as_mut(&self) -> &mut Player<'static> { 39 | unsafe { &mut *(self.0 as *mut Player<'static>) } 40 | } 41 | } 42 | 43 | impl AsRef> for PtrMutPlayer { 44 | fn as_ref(&self) -> &Player<'static> { 45 | unsafe { &*(self.0 as *mut Player<'static>) } 46 | } 47 | } 48 | 49 | unsafe impl Send for PtrMutPlayer {} 50 | 51 | impl PlayerDigEvent { 52 | pub fn new( 53 | button: Button, 54 | location: glm::TVec3, 55 | player: *mut Player 56 | ) -> Self { 57 | Self { 58 | button_press: button, 59 | dig_spot: location, 60 | p_player: PtrMutPlayer(player as _) 61 | } 62 | } 63 | 64 | fn dig(&self, world: &mut World) { 65 | let x = self.dig_spot.x as i32; 66 | let y = self.dig_spot.y as i32; 67 | let z = self.dig_spot.z as i32; 68 | match self.button_press { 69 | Button::Left => { 70 | let block = world.get_block(x, y, z); 71 | let material = Material::from_block_id(BlockId::try_from( 72 | block.id as i32).unwrap()); 73 | self.p_player.as_mut().add_item(material); 74 | world.update_chunk(x, y, z); 75 | world.set_block(x, y, z, ChunkBlock::new_with_block_type(0)); 76 | } 77 | Button::Right => { 78 | let stack = self.p_player.as_mut().get_held_items_mut(); 79 | let material = stack.material(); 80 | 81 | if material.id == ID::Nothing { 82 | return; 83 | } else { 84 | stack.remove(); 85 | world.update_chunk(x, y, z); 86 | world.set_block(x, y, z, ChunkBlock::new_with_block_id(material.to_block_id())); 87 | } 88 | } 89 | _ => {} 90 | } 91 | } 92 | } 93 | 94 | impl IWorldEvent for PlayerDigEvent { 95 | fn handle(&self, world: &mut World) { 96 | let chunk_location = World::get_chunk_xz( 97 | self.dig_spot.x as i32, self.dig_spot.z as i32); 98 | 99 | if world.get_chunk_manager().chunk_loaded_at(chunk_location.x, chunk_location.z) { 100 | self.dig(world); 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /src/world/event/world_event.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::world::world::World; 18 | 19 | pub trait IWorldEvent: Send { 20 | fn handle(&self, world: &mut World); 21 | } -------------------------------------------------------------------------------- /src/world/generation/biome/biome.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::maths::noise_generator::{NoiseGenerator, NoiseParameters}; 18 | use crate::util::random::Random; 19 | use crate::world::block::block_id::BlockId; 20 | use crate::world::block::chunk_block::ChunkBlock; 21 | use crate::world::chunk::chunk::Chunk; 22 | 23 | pub trait Biome { 24 | fn get_plant(&self, rand: &Random) -> ChunkBlock; 25 | fn get_top_block(&self, rand: &Random) -> ChunkBlock; 26 | fn get_under_water_block(&self, rand: &Random) -> ChunkBlock; 27 | fn get_beach_block(&self, _rand: &Random) -> ChunkBlock { 28 | ChunkBlock::new_with_block_id(BlockId::Sand) 29 | } 30 | fn make_tree(&self, rand: &Random, chunk: &mut Chunk, x: i32, y: i32, z: i32); 31 | 32 | fn get_height(&self, x: i32, z: i32, chunk_x: i32, chunk_z: i32) -> i32; 33 | fn get_tree_frequency(&self) -> i32; 34 | fn get_plant_frequency(&self) -> i32; 35 | } 36 | 37 | pub struct BiomeBase { 38 | pub height_generator: NoiseGenerator, 39 | pub tree_freq: i32, 40 | pub plant_freq: i32 41 | } 42 | 43 | impl BiomeBase { 44 | pub fn new( 45 | parameters: NoiseParameters, 46 | tree_freq: i32, 47 | plant_freq: i32, 48 | seed: i32 49 | ) -> Self { 50 | let mut result = Self { 51 | height_generator: NoiseGenerator::new(seed), 52 | tree_freq, 53 | plant_freq 54 | }; 55 | result.height_generator.set_parameters(parameters); 56 | result 57 | } 58 | } -------------------------------------------------------------------------------- /src/world/generation/biome/desert_biome.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::maths::noise_generator::NoiseParameters; 18 | use crate::util::random::Random; 19 | use crate::world::block::block_id::BlockId; 20 | use crate::world::block::chunk_block::ChunkBlock; 21 | use crate::world::chunk::chunk::Chunk; 22 | use crate::world::generation::biome::biome::{Biome, BiomeBase}; 23 | use crate::world::generation::structure::tree_generator; 24 | use crate::world::world_constants::WATER_LEVEL; 25 | 26 | pub struct DesertBiome { 27 | biome: BiomeBase 28 | } 29 | 30 | impl DesertBiome { 31 | pub fn new(seed: i32) -> Self { 32 | Self { 33 | biome: BiomeBase::new(Self::get_noise_parameters(), 1350, 500, seed) 34 | } 35 | } 36 | 37 | fn get_noise_parameters() -> NoiseParameters { 38 | let mut height_params = NoiseParameters::default(); 39 | height_params.octaves = 9; 40 | height_params.amplitude = 80; 41 | height_params.smoothness = 335; 42 | height_params.height_offset = -7; 43 | height_params.roughness = 0.56; 44 | 45 | height_params 46 | } 47 | } 48 | 49 | impl Biome for DesertBiome { 50 | fn get_plant(&self, _: &Random) -> ChunkBlock { 51 | ChunkBlock::new_with_block_id(BlockId::DeadShrub) 52 | } 53 | 54 | fn get_top_block(&self, _: &Random) -> ChunkBlock { 55 | ChunkBlock::new_with_block_id(BlockId::Sand) 56 | } 57 | 58 | fn get_under_water_block(&self, _: &Random) -> ChunkBlock { 59 | ChunkBlock::new_with_block_id(BlockId::Sand) 60 | } 61 | 62 | fn make_tree(&self, rand: &Random, chunk: &mut Chunk, x: i32, y: i32, z: i32) { 63 | if y < WATER_LEVEL as i32 + 15 { 64 | if rand.int_in_range(0..=100) > 75 { 65 | tree_generator::make_palm_tree(chunk, rand, x, y, z); 66 | } else { 67 | tree_generator::make_cactus(chunk, rand, x, y, z); 68 | } 69 | } else { 70 | tree_generator::make_cactus(chunk, rand, x, y, z); 71 | } 72 | } 73 | 74 | fn get_height(&self, x: i32, z: i32, chunk_x: i32, chunk_z: i32) -> i32 { 75 | self.biome.height_generator.get_height(x, z, chunk_x, chunk_z) as _ 76 | } 77 | 78 | fn get_tree_frequency(&self) -> i32 { 79 | self.biome.tree_freq 80 | } 81 | 82 | fn get_plant_frequency(&self) -> i32 { 83 | self.biome.plant_freq 84 | } 85 | } -------------------------------------------------------------------------------- /src/world/generation/biome/grassland_biome.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::maths::noise_generator::NoiseParameters; 18 | use crate::util::random::Random; 19 | use crate::world::block::block_id::BlockId; 20 | use crate::world::block::chunk_block::ChunkBlock; 21 | use crate::world::chunk::chunk::Chunk; 22 | use crate::world::generation::biome::biome::{Biome, BiomeBase}; 23 | use crate::world::generation::structure::tree_generator; 24 | 25 | pub struct GrasslandBiome { 26 | biome: BiomeBase 27 | } 28 | 29 | impl GrasslandBiome { 30 | pub fn new(seed: i32) -> Self { 31 | Self { 32 | biome: BiomeBase::new(Self::get_noise_parameters(), 1000, 20, seed) 33 | } 34 | } 35 | 36 | fn get_noise_parameters() -> NoiseParameters { 37 | let mut height_params = NoiseParameters::default(); 38 | height_params.octaves = 9; 39 | height_params.amplitude = 85; 40 | height_params.smoothness = 235; 41 | height_params.height_offset = -20; 42 | height_params.roughness = 0.51; 43 | 44 | height_params 45 | } 46 | } 47 | 48 | impl Biome for GrasslandBiome { 49 | fn get_plant(&self, rand: &Random) -> ChunkBlock { 50 | if rand.int_in_range(0..=10) > 6 { 51 | ChunkBlock::new_with_block_id(BlockId::Rose) 52 | } else { 53 | ChunkBlock::new_with_block_id(BlockId::TallGrass) 54 | } 55 | } 56 | 57 | fn get_top_block(&self, _: &Random) -> ChunkBlock { 58 | ChunkBlock::new_with_block_id(BlockId::Grass) 59 | } 60 | 61 | fn get_under_water_block(&self, rand: &Random) -> ChunkBlock { 62 | if rand.int_in_range(0..=10) > 6 { 63 | ChunkBlock::new_with_block_id(BlockId::Dirt) 64 | } else { 65 | ChunkBlock::new_with_block_id(BlockId::Sand) 66 | } 67 | } 68 | 69 | fn get_beach_block(&self, rand: &Random) -> ChunkBlock { 70 | if rand.int_in_range(0..=10) > 2 { 71 | ChunkBlock::new_with_block_id(BlockId::Grass) 72 | } else { 73 | ChunkBlock::new_with_block_id(BlockId::Dirt) 74 | } 75 | } 76 | 77 | fn make_tree(&self, rand: &Random, chunk: &mut Chunk, x: i32, y: i32, z: i32) { 78 | tree_generator::make_oak_tree(chunk, rand, x, y, z); 79 | } 80 | 81 | fn get_height(&self, x: i32, z: i32, chunk_x: i32, chunk_z: i32) -> i32 { 82 | self.biome.height_generator.get_height(x, z, chunk_x, chunk_z) as _ 83 | } 84 | 85 | fn get_tree_frequency(&self) -> i32 { 86 | self.biome.tree_freq 87 | } 88 | 89 | fn get_plant_frequency(&self) -> i32 { 90 | self.biome.plant_freq 91 | } 92 | } -------------------------------------------------------------------------------- /src/world/generation/biome/light_forest.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::maths::noise_generator::NoiseParameters; 18 | use crate::util::random::Random; 19 | use crate::world::block::block_id::BlockId; 20 | use crate::world::block::chunk_block::ChunkBlock; 21 | use crate::world::chunk::chunk::Chunk; 22 | use crate::world::generation::biome::biome::{Biome, BiomeBase}; 23 | use crate::world::generation::structure::tree_generator; 24 | 25 | pub struct LightForest { 26 | biome: BiomeBase 27 | } 28 | 29 | impl LightForest { 30 | pub fn new(seed: i32) -> Self { 31 | Self { 32 | biome: BiomeBase::new(Self::get_noise_parameters(), 60, 80, seed) 33 | } 34 | } 35 | 36 | fn get_noise_parameters() -> NoiseParameters { 37 | let mut height_params = NoiseParameters::default(); 38 | height_params.octaves = 5; 39 | height_params.amplitude = 100; 40 | height_params.smoothness = 195; 41 | height_params.height_offset = -32; 42 | height_params.roughness = 0.52; 43 | 44 | height_params 45 | } 46 | } 47 | 48 | impl Biome for LightForest { 49 | fn get_plant(&self, rand: &Random) -> ChunkBlock { 50 | if rand.int_in_range(0..=10) > 8 { 51 | ChunkBlock::new_with_block_id(BlockId::Rose) 52 | } else { 53 | ChunkBlock::new_with_block_id(BlockId::TallGrass) 54 | } 55 | } 56 | 57 | fn get_top_block(&self, _: &Random) -> ChunkBlock { 58 | ChunkBlock::new_with_block_id(BlockId::Grass) 59 | } 60 | 61 | fn get_under_water_block(&self, rand: &Random) -> ChunkBlock { 62 | if rand.int_in_range(0..=10) > 9 { 63 | ChunkBlock::new_with_block_id(BlockId::Sand) 64 | } else { 65 | ChunkBlock::new_with_block_id(BlockId::Dirt) 66 | } 67 | } 68 | 69 | fn make_tree(&self, rand: &Random, chunk: &mut Chunk, x: i32, y: i32, z: i32) { 70 | tree_generator::make_oak_tree(chunk, rand, x, y, z); 71 | } 72 | 73 | fn get_height(&self, x: i32, z: i32, chunk_x: i32, chunk_z: i32) -> i32 { 74 | self.biome.height_generator.get_height(x, z, chunk_x, chunk_z) as _ 75 | } 76 | 77 | fn get_tree_frequency(&self) -> i32 { 78 | self.biome.tree_freq 79 | } 80 | 81 | fn get_plant_frequency(&self) -> i32 { 82 | self.biome.plant_freq 83 | } 84 | } -------------------------------------------------------------------------------- /src/world/generation/biome/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod biome; 18 | pub mod desert_biome; 19 | pub mod light_forest; 20 | pub mod ocean_biome; 21 | pub mod temperate_forest_biome; 22 | pub mod grassland_biome; -------------------------------------------------------------------------------- /src/world/generation/biome/ocean_biome.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::maths::noise_generator::NoiseParameters; 18 | use crate::util::random::Random; 19 | use crate::world::block::block_id::BlockId; 20 | use crate::world::block::chunk_block::ChunkBlock; 21 | use crate::world::chunk::chunk::Chunk; 22 | use crate::world::generation::biome::biome::{Biome, BiomeBase}; 23 | use crate::world::generation::structure::tree_generator; 24 | 25 | pub struct OceanBiome { 26 | biome: BiomeBase 27 | } 28 | 29 | impl OceanBiome { 30 | pub fn new(seed: i32) -> Self { 31 | Self { 32 | biome: BiomeBase::new(Self::get_noise_parameters(), 50, 100, seed) 33 | } 34 | } 35 | 36 | fn get_noise_parameters() -> NoiseParameters { 37 | let mut height_params = NoiseParameters::default(); 38 | height_params.octaves = 7; 39 | height_params.amplitude = 43; 40 | height_params.smoothness = 55; 41 | height_params.height_offset = 0; 42 | height_params.roughness = 0.50; 43 | 44 | height_params 45 | } 46 | } 47 | 48 | impl Biome for OceanBiome { 49 | fn get_plant(&self, rand: &Random) -> ChunkBlock { 50 | if rand.int_in_range(0..=10) > 6 { 51 | ChunkBlock::new_with_block_id(BlockId::Rose) 52 | } else { 53 | ChunkBlock::new_with_block_id(BlockId::TallGrass) 54 | } 55 | } 56 | 57 | fn get_top_block(&self, _: &Random) -> ChunkBlock { 58 | ChunkBlock::new_with_block_id(BlockId::Grass) 59 | } 60 | 61 | fn get_under_water_block(&self, _: &Random) -> ChunkBlock { 62 | ChunkBlock::new_with_block_id(BlockId::Sand) 63 | } 64 | 65 | fn make_tree(&self, rand: &Random, chunk: &mut Chunk, x: i32, y: i32, z: i32) { 66 | if rand.int_in_range(0..=5) < 3 { 67 | tree_generator::make_palm_tree(chunk, rand, x, y, z); 68 | } else { 69 | tree_generator::make_oak_tree(chunk, rand, x, y, z); 70 | } 71 | } 72 | 73 | fn get_height(&self, x: i32, z: i32, chunk_x: i32, chunk_z: i32) -> i32 { 74 | self.biome.height_generator.get_height(x, z, chunk_x, chunk_z) as _ 75 | } 76 | 77 | fn get_tree_frequency(&self) -> i32 { 78 | self.biome.tree_freq 79 | } 80 | 81 | fn get_plant_frequency(&self) -> i32 { 82 | self.biome.plant_freq 83 | } 84 | } -------------------------------------------------------------------------------- /src/world/generation/biome/temperate_forest_biome.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::maths::noise_generator::NoiseParameters; 18 | use crate::util::random::Random; 19 | use crate::world::block::block_id::BlockId; 20 | use crate::world::block::chunk_block::ChunkBlock; 21 | use crate::world::chunk::chunk::Chunk; 22 | use crate::world::generation::biome::biome::{Biome, BiomeBase}; 23 | use crate::world::generation::structure::tree_generator; 24 | 25 | pub struct TemperateForestBiome { 26 | biome: BiomeBase 27 | } 28 | 29 | impl TemperateForestBiome { 30 | pub fn new(seed: i32) -> Self { 31 | Self { 32 | biome: BiomeBase::new(Self::get_noise_parameters(), 55, 75, seed) 33 | } 34 | } 35 | 36 | fn get_noise_parameters() -> NoiseParameters { 37 | let mut height_params = NoiseParameters::default(); 38 | height_params.octaves = 5; 39 | height_params.amplitude = 100; 40 | height_params.smoothness = 195; 41 | height_params.height_offset = -30; 42 | height_params.roughness = 0.52; 43 | 44 | height_params 45 | } 46 | } 47 | 48 | impl Biome for TemperateForestBiome { 49 | fn get_plant(&self, _: &Random) -> ChunkBlock { 50 | ChunkBlock::new_with_block_id(BlockId::TallGrass) 51 | } 52 | 53 | fn get_top_block(&self, rand: &Random) -> ChunkBlock { 54 | if rand.int_in_range(0..=10) < 8 { 55 | ChunkBlock::new_with_block_id(BlockId::Grass) 56 | } else { 57 | ChunkBlock::new_with_block_id(BlockId::Dirt) 58 | } 59 | } 60 | 61 | fn get_under_water_block(&self, rand: &Random) -> ChunkBlock { 62 | if rand.int_in_range(0..=10) > 8 { 63 | ChunkBlock::new_with_block_id(BlockId::Dirt) 64 | } else { 65 | ChunkBlock::new_with_block_id(BlockId::Sand) 66 | } 67 | } 68 | 69 | fn make_tree(&self, rand: &Random, chunk: &mut Chunk, x: i32, y: i32, z: i32) { 70 | tree_generator::make_oak_tree(chunk, rand, x, y, z); 71 | } 72 | 73 | fn get_height(&self, x: i32, z: i32, chunk_x: i32, chunk_z: i32) -> i32 { 74 | self.biome.height_generator.get_height(x, z, chunk_x, chunk_z) as _ 75 | } 76 | 77 | fn get_tree_frequency(&self) -> i32 { 78 | self.biome.tree_freq 79 | } 80 | 81 | fn get_plant_frequency(&self) -> i32 { 82 | self.biome.plant_freq 83 | } 84 | } -------------------------------------------------------------------------------- /src/world/generation/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod terrain_generator; 18 | pub mod classic_over_world_generator; 19 | pub mod biome; 20 | pub mod structure; 21 | pub mod super_flat_generator; -------------------------------------------------------------------------------- /src/world/generation/structure/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod structure_builder; 18 | pub mod tree_generator; -------------------------------------------------------------------------------- /src/world/generation/structure/structure_builder.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::world::block::block_id::BlockId; 18 | use crate::world::block::chunk_block::ChunkBlock; 19 | use crate::world::chunk::chunk::{Chunk, IChunk}; 20 | 21 | #[derive(Copy, Clone, Default)] 22 | pub struct Block { 23 | id: BlockId, 24 | x: i32, 25 | y: i32, 26 | z: i32 27 | } 28 | 29 | #[derive(Clone, Default)] 30 | pub struct StructureBuilder { 31 | blocks: Vec 32 | } 33 | 34 | impl Block { 35 | pub fn new(id: BlockId, x: i32, y: i32, z: i32) -> Self { 36 | Self { id, x, y, z } 37 | } 38 | } 39 | 40 | impl StructureBuilder { 41 | pub fn build(&self, chunk: &mut Chunk) { 42 | for block in self.blocks.iter() { 43 | chunk.set_block(block.x, block.y, block.z, 44 | ChunkBlock::new_with_block_id(block.id)); 45 | } 46 | } 47 | 48 | pub fn make_column( 49 | &mut self, 50 | x: i32, 51 | z: i32, 52 | y_start: i32, 53 | height: i32, 54 | block: BlockId 55 | ) { 56 | for y in y_start..y_start + height { 57 | self.add_block(x, y, z, block); 58 | } 59 | } 60 | 61 | pub fn make_row_x( 62 | &mut self, 63 | x_start: i32, 64 | x_end: i32, 65 | y: i32, 66 | z: i32, 67 | block: BlockId 68 | ) { 69 | for x in x_start..=x_end { 70 | self.add_block(x, y, z, block); 71 | } 72 | } 73 | 74 | pub fn make_row_z( 75 | &mut self, 76 | z_start: i32, 77 | z_end: i32, 78 | x: i32, 79 | y: i32, 80 | block: BlockId 81 | ) { 82 | for z in z_start..=z_end { 83 | self.add_block(x, y, z, block); 84 | } 85 | } 86 | 87 | pub fn fill( 88 | &mut self, 89 | y: i32, 90 | x_start: i32, 91 | x_end: i32, 92 | z_start: i32, 93 | z_end: i32, 94 | block: BlockId 95 | ) { 96 | for x in x_start..x_end { 97 | for z in z_start..z_end { 98 | self.add_block(x, y, z, block); 99 | } 100 | } 101 | } 102 | 103 | pub fn add_block( 104 | &mut self, 105 | x: i32, 106 | y: i32, 107 | z: i32, 108 | block: BlockId 109 | ) { 110 | self.blocks.push(Block::new(block, x, y, z)); 111 | } 112 | } -------------------------------------------------------------------------------- /src/world/generation/structure/tree_generator.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::util::random::Random; 18 | use crate::world::block::block_id::BlockId; 19 | use crate::world::chunk::chunk::Chunk; 20 | use crate::world::generation::structure::structure_builder::StructureBuilder; 21 | 22 | const CACTUS: BlockId = BlockId::Cactus; 23 | 24 | fn make_cactus_1(chunk: &mut Chunk, rand: &Random, x: i32, y: i32, z: i32) { 25 | let mut builder = StructureBuilder::default(); 26 | builder.make_column(x, z, y, rand.int_in_range(4..=7), CACTUS); 27 | builder.build(chunk); 28 | } 29 | 30 | fn make_cactus_2(chunk: &mut Chunk, rand: &Random, x: i32, y: i32, z: i32) { 31 | let mut builder = StructureBuilder::default(); 32 | let height: i32 = rand.int_in_range(6..=8); 33 | builder.make_column(x, z, y, height, CACTUS); 34 | 35 | let stem = height / 2; 36 | 37 | builder.make_row_x(x - 2, x + 2, stem + y, z, CACTUS); 38 | builder.add_block(x - 2, stem + y + 1, z, CACTUS); 39 | builder.add_block(x - 2, stem + y + 2, z, CACTUS); 40 | builder.add_block(x + 2, stem + y + 1, z, CACTUS); 41 | 42 | builder.build(chunk); 43 | } 44 | 45 | fn make_cactus_3(chunk: &mut Chunk, rand: &Random, x: i32, y: i32, z: i32) { 46 | let mut builder = StructureBuilder::default(); 47 | let height: i32 = rand.int_in_range(6..=8); 48 | builder.make_column(x, z, y, height, CACTUS); 49 | 50 | let stem = height / 2; 51 | 52 | builder.make_row_x(x - 2, x + 2, stem + y, z, CACTUS); 53 | builder.add_block(x, stem + y + 1, z - 2, CACTUS); 54 | builder.add_block(x, stem + y + 2, z - 2, CACTUS); 55 | builder.add_block(x, stem + y + 1, z + 2, CACTUS); 56 | 57 | builder.build(chunk); 58 | } 59 | 60 | pub fn make_oak_tree(chunk: &mut Chunk, rand: &Random, x: i32, y: i32, z: i32) { 61 | let mut builder = StructureBuilder::default(); 62 | 63 | let h: i32 = rand.int_in_range(4..=7); 64 | let leaf_size = 2; 65 | 66 | let new_y = h + y; 67 | builder.fill(new_y, x - leaf_size, x + leaf_size, 68 | z - leaf_size, z + leaf_size, 69 | BlockId::OakLeaf); 70 | builder.fill(new_y - 1, x - leaf_size, x + leaf_size, 71 | z - leaf_size, z + leaf_size, 72 | BlockId::OakLeaf); 73 | 74 | for z_leaf in -leaf_size + 1 ..= leaf_size - 1 { 75 | builder.add_block(x, new_y + 1, z + z_leaf, BlockId::OakLeaf); 76 | } 77 | 78 | for x_leaf in -leaf_size + 1 ..= leaf_size - 1 { 79 | builder.add_block(x + x_leaf, new_y + 1, z, BlockId::OakLeaf); 80 | } 81 | 82 | builder.make_column(x, z, y, h, BlockId::OakBark); 83 | builder.build(chunk); 84 | } 85 | 86 | pub fn make_palm_tree(chunk: &mut Chunk, rand: &Random, x: i32, y: i32, z: i32) { 87 | let mut builder = StructureBuilder::default(); 88 | 89 | let height: i32 = rand.int_in_range(7..=9); 90 | let diameter: i32 = rand.int_in_range(4..=6); 91 | 92 | for x_leaf in -diameter .. diameter { 93 | builder.add_block(x_leaf + x, y + height, z, BlockId::OakLeaf); 94 | } 95 | for z_leaf in -diameter .. diameter { 96 | builder.add_block(x, y + height, z_leaf + z, BlockId::OakLeaf); 97 | } 98 | 99 | builder.add_block(x, y + height - 1, z + diameter, BlockId::OakLeaf); 100 | builder.add_block(x, y + height - 1, z - diameter, BlockId::OakLeaf); 101 | builder.add_block(x + diameter, y + height - 1, z, BlockId::OakLeaf); 102 | builder.add_block(x - diameter, y + height - 1, z, BlockId::OakLeaf); 103 | builder.add_block(x, y + height - 1, z, BlockId::OakLeaf); 104 | 105 | builder.make_column(x, z, y, height, BlockId::OakBark); 106 | builder.build(chunk); 107 | } 108 | 109 | pub fn make_cactus(chunk: &mut Chunk, rand: &Random, x: i32, y: i32, z: i32) { 110 | let cac: i32 = rand.int_in_range(0..=2); 111 | 112 | match cac { 113 | 0 => { 114 | make_cactus_1(chunk, rand, x, y, z); 115 | } 116 | 1 => { 117 | make_cactus_2(chunk, rand, x, y, z); 118 | } 119 | 2 => { 120 | make_cactus_3(chunk, rand, x, y, z); 121 | } 122 | _ => {} 123 | } 124 | } -------------------------------------------------------------------------------- /src/world/generation/super_flat_generator.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::world::block::block_id::BlockId; 18 | use crate::world::block::chunk_block::ChunkBlock; 19 | use crate::world::chunk::chunk::{Chunk, IChunk}; 20 | use crate::world::generation::terrain_generator::TerrainGenerator; 21 | use crate::world::world_constants::CHUNK_SIZE; 22 | 23 | #[derive(Default)] 24 | pub struct SuperFlatGenerator { 25 | } 26 | 27 | impl TerrainGenerator for SuperFlatGenerator { 28 | fn generate_terrain_for(&mut self, chunk: &mut Chunk) { 29 | for x in 0..CHUNK_SIZE { 30 | for z in 0..CHUNK_SIZE { 31 | chunk.set_block(x as _, 0, z as _, ChunkBlock::new_with_block_id(BlockId::Stone)); 32 | chunk.set_block(x as _, 1, z as _, ChunkBlock::new_with_block_id(BlockId::Dirt)); 33 | chunk.set_block(x as _, 2, z as _, ChunkBlock::new_with_block_id(BlockId::Dirt)); 34 | chunk.set_block(x as _, 3, z as _, ChunkBlock::new_with_block_id(BlockId::Dirt)); 35 | chunk.set_block(x as _, 4, z as _, ChunkBlock::new_with_block_id(BlockId::Grass)); 36 | } 37 | } 38 | } 39 | 40 | fn get_minimum_spawn_height(&self) -> i32 { 41 | 1 42 | } 43 | } -------------------------------------------------------------------------------- /src/world/generation/terrain_generator.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | use crate::world::chunk::chunk::Chunk; 18 | 19 | pub trait TerrainGenerator { 20 | fn generate_terrain_for(&mut self, chunk: &mut Chunk); 21 | fn get_minimum_spawn_height(&self) -> i32; 22 | } -------------------------------------------------------------------------------- /src/world/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub mod world; 18 | pub mod chunk; 19 | pub mod world_constants; 20 | pub mod block; 21 | pub mod event; 22 | pub mod generation; -------------------------------------------------------------------------------- /src/world/world_constants.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Copyright 2024 src_resources 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | pub const CHUNK_SIZE: usize = 16; 18 | pub const CHUNK_AREA: usize = CHUNK_SIZE * CHUNK_SIZE; 19 | pub const CHUNK_VOLUME: usize = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE; 20 | pub const WATER_LEVEL: usize = 64; --------------------------------------------------------------------------------