unarelith / openminer Goto Github PK
View Code? Open in Web Editor NEWMinecraft-like game engine written in C++17 with a client/server architecture and support for Lua modding
License: GNU Lesser General Public License v2.1
Minecraft-like game engine written in C++17 with a client/server architecture and support for Lua modding
License: GNU Lesser General Public License v2.1
Hey! I found this yesterday. A few days ago I started trying to improve this Minecraft-like game, but then I decided to look at some other implementations first, and I gave yours a try. It looks very promising so far!
However, I don't really like SDL, so I made it support SFML (2.4+). I created a branch 'SFML-and-SDL', where I added a bunch of #ifdef
s for all SDL code until it worked :D Now you can choose one with a global macro USE_SDL or USE_SFML. Of course it's not very nice having these ugly macros in some places, but it's not too bad I think.
So... is any of that helpful? xD I've seen in some places you kind of replicated some of the SFML classes (Vector2/3, Rect, ...) with the same names. Were you already planning to switch to SFML soon? I could now easily remove all SDL specific code to get a clean SFML version if you want, but there are some small problems with it still. With some more tricks I could also get rid of many of the macros I think, if you are interested in having both in one version. But it's probably a bad idea... I will probably make another branch 'SFML' and keep both updated with future commits, maybe they will be useful at some point.
Some general notes:
On Windows, client disconnection doesn't work as expected.
The engine should be able to handle dimensions, like the Nether or the Ender in Minecraft.
It should be possible to teleport the player between dimensions using Lua.
Since #14 was merged, texture bleeding appeared.
The only fix would be to use separate textures for each block.
The engine could switch later to Z-up because of the following:
However this could require a lot of work to make the change, so this will definitely wait.
If you have arguments for Y-up or Z-up you can comment this issue.
Thanks to @p_gimeno for pointing that up.
Currently, the player position is at the center top of its bounding box.
However, its position should be at the center bottom of this box.
It's possible to place a block inside a player, this shouldn't be happening.
This should be easy to fix by checking intersection between block bounding box and player bounding box.
Using single-precision floating point numbers can seriously affect bounding box and meshes that are far from (0;0;0).
However using double-precision floating point numbers can affect performance and data transfers.
Evaluate the pros and cons of such a change.
Thanks to p_gimeno for pointing this out.
After trying to compile the game on Windows with MinGW to see if everything was still working, I noticed that collisions are completely fucked up.
Sometimes the player is one block lower than normal, sometimes it goes through the floor, getting stuck a few blocks below the surface.
The problem is caused by this commit: 7ce3321
Another interesting feature will be to have a custom draw type for blocks, which will be similar to Minetest nodeboxes.
Modders will be able to create custom meshes by defining sub-parts of the block.
This will be useful to make slabs, stairs, torches, etc...
What could be interesting for this part, is to find a way to optimize meshes. For example, stairs are made of two sub-parts, one being 1
and the other being 23
.
1
23
But the bottom face of 1
and the top face of 3
are useless, so it's definitely better to avoid drawing them.
My solution would be to separate custom meshes from block definition.
For example, instead of doing this:
mod:block {
-- ...
drawtype = "subparts",
subparts = {
{1, 0.5, 1},
{0.5, 0.5, 1}
},
-- ...
It could be possible to do this:
mod:mesh {
name = "stairs",
subparts = {
{1, 0.5, 1},
{0.5, 0.5, 1}
}
}
mod:block {
-- ...
drawtype = "subparts",
mesh = "stairs"
-- ...
}
That way, meshes can be optimized on mod loading, and every block that shares the same mesh will use that optimization. Moreover, it will allow modders to share custom meshes between mods. So if this mod is called mymod
, another modder can use this stairs mesh by writing:
mesh = "mymod:stairs"
Usually, when colliding with a block you can still move sideways.
Currently, this is not possible for blocks placed at x=-1 when being at x=0.
Currently, the only way to use custom textures is to replace those in mods/default/textures
.
However, this only works for blocks/items textures.
A real texture pack system should be able to:
Once it's done, replace every textures by Faithful 32x ones, and provide a way to use original Minecraft textures from a legit copy of the game.
When targeting an area outside the world limit, it's possible to target blocks at the other side of the world.
This is not a problem anymore since the world is infinite but it could be a problem if I decide to add a customizable world height.
It's possible to see cut trees, and this problem is fixed when disconnecting/reconnecting to the server.
This issue is caused by a bad chunk update. When a tree generates on chunk A, it could generate on chunk B too. If chunk B isn't sent again when chunk A generates the tree, the client will not be able to see the complete tree. (Fixed by b2fd4e6)
Another problem, maybe related but isn't fixed by reconnecting to the server, is the sunlight. The trees can be completely lit on one side, and not lit at all on another side.
When aiming between two blocks, it's sometimes possible to replace one of these blocks.
It's happening because of the raytracing algorithm located in BlockCursor.cpp.
The face is not detected correctly in that case, causing that problem.
/
on AZERTY keyboard should be bindable too because this is basically Shift+:
Ticket opened on SDL2 bug tracker: https://bugzilla.libsdl.org/show_bug.cgi?id=5000
I'm having issues when trying to compile OpenMiner.
-DGAMEKIT_LIBRARIES
and -DGAMEKIT_INCLUDE_DIR
and CMake found it. I worked around this by editing the top CMakeLists.txt and replacing include_directories(${GAMEKIT_INCLUDE_DIRS})
(plural DIRS) with include_directories(${GAMEKIT_INCLUDE_DIR})
. I don't know why this is necessary. I know nothing about cmake..../OpenMiner/common/source/core/Registry.cpp: In member function ‘Item& Registry::registerItem(u32, const string&, const string&)’:
.../OpenMiner/common/source/core/Registry.cpp:25:29: error: invalid initialization of non-const reference of type ‘Item&’ from an rvalue of type ‘void’
return m_items.emplace_back(internalID, textureID, id, name);
Would you please advise me on how to get compilation to continue?
Making the world infinite will be a big amount of work, but it's needed to move on to the next part.
When you're standing in the surface and try to break a block underwater, the block breaking animation is not displayed.
It's probably because the water mesh hides it.
There's exactly the same problem if you try to break a block on the surface while being underwater.
Lighting has a lot of issues that I'll try to describe here.
The relevant files are:
Light propagation is implemented with a basic breadth-first search algorithm, which is described in those two articles:
Torchlight isn't exactly implemented as described in the first article because it causes weird ambient occlusion effects:
OpenMiner/common/source/world/ChunkLightmap.cpp
Lines 91 to 98 in 8aa86f8
What it currently looks like:
NB: In this case the light cannot be blocked
What it looks like when I do like the article:
NB: In this case the light can be blocked
Smooth lighting relevant code:
OpenMiner/client/source/world/ChunkBuilder.cpp
Lines 325 to 339 in 8aa86f8
With the same change as above, here what the world looks like without smooth lighting:
Sunlight downward propagation causes weird effects without smooth lighting:
OpenMiner/common/source/world/ChunkLightmap.cpp
Lines 146 to 150 in 8aa86f8
The top water blocks should have an height of 0.9375 (15/16) instead of 1.0.
The client should be able to run a "private" server to play a singleplayer game without an external server.
Solution: Use AABB collision check instead of 4 points.
See #122.
SettingsMenuState
should reload when GUI scale is changedHotbar
and BlockInfoWidget
should be updatedTitleScreenState
should be updatedgk::TextInput
in ServerConnectState
should be affected by GUI scaleI'm currently using official Minecraft assets, and I shouldn't do that.
A main menu could be useful, especially since network part is coming.
The requirements for the main menu are:
gk::Image
)gk::Text
using Minecraftia font which already is in the repo)Important things to know:
Application
under the name font-title
gk::ApplicationState
subclass needs to be created, refer to PauseMenuState
implementation to get an usage example for this classPauseMenuState
with this action:m_stateStack->push<MainMenuState>();
The server should check that:
The client-side check made to fix #32 only checks the current player and the state of the world the client has. The server should check other players and its own state of the world (which is the real one). For example if two clients try to place a block at the same time, the server should only allow the first block placement packet it receives.
Actually, the client should also check for other players but that's another issue.
A chat system should be implemented, with the support for server commands.
Example commands:
/tp x y z
: teleports the player to (x;y;z)/spawn
: teleports to spawn/sethome
: set the current location as the player home/home
: teleports the player to his home if defined, otherwise prints an error messageAs discussed in IRC, there is a problem in some video cards that causes a flicker very similar to Z-fighting in lighting, leaves and grass.
I've managed to fix it with the following patch:
diff --git a/resources/shaders/game.f.glsl b/resources/shaders/game.f.glsl
index 2858f63..bd29b6d 100644
--- a/resources/shaders/game.f.glsl
+++ b/resources/shaders/game.f.glsl
@@ -20,19 +20,23 @@ vec4 light(vec4 color, vec3 lightColor, vec4 lightPosition, float ambientIntensi
vec4 fog(vec4 color, float fogCoord, float fogStart, float fogEnd);
void main() {
+ float blockID = floor(v_blockID + 0.5);
+ float blockFace = floor(v_blockFace + 0.5);
+ float lightCheck = floor(v_lightValue.x + 0.5);
+
// Discard if the pixel is too far away
- if(v_blockID != -1 && v_dist > u_renderDistance) discard;
+ if(blockID != -1. && v_dist > u_renderDistance) discard;
vec4 color = getColor();
- if (v_blockID == 8) { // Water
+ if (blockID == 8.) { // Water
color.a = 0.85;
}
- else if (v_blockID == 4) { // Leaves
+ else if (blockID == 4.) { // Leaves
color += vec4(-0.5, -0.15, -0.4, 0);
/* if (v_dist > 20 && color.a == 0) */
/* color.a = 0.5; */
}
- else if (v_blockID == 3) { // Grass
+ else if (blockID == 3.) { // Grass
if (color.r == color.g && color.r == color.b) {
color += vec4(-0.3, -0.1, -0.25, 0);
/* color += vec4(-0.4, -0.15, -0.3, 0); */
@@ -40,7 +44,7 @@ void main() {
}
// Very cheap "transparency": don't draw pixels with a low alpha value
- if(color.a < 0.3 && v_blockID != -1) discard;
+ if(color.a < 0.3 && blockID != -1.) discard;
// FIXME: FINISH THIS WITH PROPER CODE AND SUN BASIC DISPLAY
// int maxTime = 5 * 1000;
@@ -49,18 +53,18 @@ void main() {
// color *= light(vec3(1.0, 1.0, 1.0), vec4(lightPosition, 1.0), 0.5, 0.5);
float minBrightness = 2.0 / 16.0;
- if (v_lightValue.x != -1) {
+ if (lightCheck != -1.) {
float ambientIntensity = max(max(v_lightValue.x, v_lightValue.y) / 16.0, minBrightness);
float diffuseIntensity = max(v_lightValue.x, v_lightValue.y) / 32.0;
// Bottom
- if (v_blockFace == 2)
+ if (blockFace == 2.)
ambientIntensity = max(ambientIntensity * 0.6, minBrightness);
// Left or Right
- if (v_blockFace == 0 || v_blockFace == 1)
+ if (blockFace == 0. || blockFace == 1.)
ambientIntensity = max(ambientIntensity * 0.75, minBrightness);
// Front or Back
- if (v_blockFace == 4 || v_blockFace == 5)
+ if (blockFace == 4. || blockFace == 5.)
ambientIntensity = max(ambientIntensity * 0.9, minBrightness);
color = light(color, vec3(1.0, 1.0, 1.0), v_coord3d, ambientIntensity, diffuseIntensity);
The patch hints at the cause: the values of the floating-point variables are not always exactly equal to the integer value they are compared with. I believe this is caused by interpolation between vertices, which may be inexact depending on the implementation. For example, this interpolation formula is not monotonic: a*(1-t)+b*t
; e.g. when a = b = 3
and t = 0.2
, in Python (with double precision floats):
>>> 3 * (1 - 0.2) + 3 * 0.2
3.0000000000000004
This can cause heavy RAM usage after a while.
Since worldgen is slower than reading a chunk from disk, I will only fix this after #26 since I'll save generated chunks.
Steps to reproduce:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.