This is pretty cool. Props for doing a massive amount of work and creating something open and extensible.
--
I just tried reading the code to learn how MineTest does voxel meshing, and it didn't go so well.
(Voxel meshing is about turning blocks into triangles efficiently, and it's surprisingly tricky. Mikola Lysenko wrote a great exposition of the problem and several solutions way back in 2012: https://0fps.net/2012/06/30/meshing-in-a-minecraft-game/ )
I was curious which approach MineTest chose, and I still don't know. I think I found the files where the meshing happens, mapblock_mesh.h/cpp. The code quality is... less than perfect.
There are 200+ line C++ functions. There's commented out code and preprocessor "#if 0" ignored code.
There's a struct that looks important, but it's called "MeshMakeData", and I don't know what it represents. The comment above just says "Mesh making stuff":
All the traits you list are superficial compared to getting the thing working and performing well in the first place :)
Heck these are the sort "clean code" practices which make your debug build run at 5 FPS (I've seen worse :). Indirections and conditionals and noise everywhere.
These get stripped in release (hopefully) but the catch is that you end up stepping in optimized code cause 5FPS can't get you where you want to test. Having all that nice cleanliness in a debug build you won't use isn't a great way to end up developing after 5 years of piling stuff up :)
Besides, you can design your systems so that they're both fast and simple; data-driven design is one such approach. Mike Acton talked about it a lot as well: https://www.youtube.com/watch?v=rX0ItVEVjHc
> Heck these are the sort "clean code" practices which make your debug build run at 5 FPS
No. Quake and Doom were both extremely performance optimized, and still had clean code.
Avoiding commented-out or otherwise dead code; naming things well; writing concise but thorough comments that explain what's going on: none of those habits hurt performance.
Great code is not just meant to compile, it's meant to be read.
Inlining code manually should almost never be necessary today. Modern compilers inline automatically.
If you do feel the need to uglify code for performance, it should only happen after profiling, not as a habit.
There is no reason, performance or otherwise, to have the main entry point of your program or the render loop for your game be in a 5000 line spaghetti file.
Why is length automatically associated to spaghetti? I've seen way too much spaghetti clean code to agree. Soon everything is its own 20 lines class file and you're buried in well documented technical debt and drowning in files; locked inside your own pretty cage.
It also doesn't have to be ugly; beauty should be in how it works not how it looks anyways. I would much, much rather focus on simplicity and let beauty emerge naturally. I've seen many projects fail even while following best practices all over the place.
Get its inner workings pretty first, then make the appearances pretty. Its incredibly harder if not outright impossible to do it in the opposite order.
If you think of performance after profiling for the first time, you've probably already wasted 90% of it without even realising it - the CPU is just that fast. Optimising at the macro level should be an habit; its the micro-level you want to optimise after profiling.
Most software today could easily be orders of magnitude faster. Doom and Quake just happen to be built on top of very well engineered foundations, which they then made pretty before releasing it to the world - it most likely wasn't that nice during development.
I'm not a programmer so forgive my armchair ignorance, but as a player I've found Minetest to run exceptionally smoothly even on 10+ year old hardware with crappy integrated video. On the other hand, Minecraft on a modernish Haswell based PC with a GTX 960 requires Optifine to run as smoothly as Minetest does on that ancient machine.
"(B)ig hairy ball of C++" or not, somehow it's optimized to the point that it feels more modern and advanced than Minecraft, if not as visually polished. My question is, is this purely a C++ vs Java thing? I've played some Java games that look and play awesome on older hardware so I have to wonder what the deal is with Minecraft.
Minecraft was simply never intended to be this big of a game. It was initially designed to be really just a game where you place blocks on other blocks. The Survival-mode, fighting against monsters etc., that was all gradually glued onto an architecture which wasn't intended for it.
One example that I happen to know, is that they never intended to have all these effects like smoke, water drops, the swirls from drinking a potion. All of this was pretty much just a hack for the longest time with no real place for it in the architecture. Eventually they fixed that and added it to the architecture, and could improve effects-performance massively with that, but there's probably still loads of things like that in the game.
Another big part of this is that Minecraft generates and loads its map in 2-dimensional chunks, or pillars if you will. So, when you move through the world, it always has to load in and keep loaded the entire height of the map, no matter if you're scraping along the clouds or if you're deep underground. If you're traveling into new terrain, it has to generate the entire height all at once, as well.
Minetest instead uses 3-dimensional chunks, i.e. cubes, and can just load/generate those freely how it needs them. So, if you're standing on a mountain and look down, it loads all visible chunks, but can just leave out those which are underground. Or if you're underground yourself, it can leave out really pretty much just all chunks altogether, except for the few which are directly around you.
This also has the effect that Minetest-maps can be unlimited in height, whereas Minecraft-maps need to be limited (currently 256 blocks; it started out at 128 blocks), as otherwise Minecraft would really just need infinite RAM and never get done with generating the map.
The original Minecraft versions had reasonable performance for a one-man app that was more about experimentation, because Notch wrote his code in a way that didn't put too much pressure on the GC. For instance block coordinates were passed as individual x,y,z arguments to each function.
When Notch passed on maintainership of the code, he apparently didn't pass on his knowledge of how far you can push the JVM, and the new developers proceeded to "modernise" the code, by, for example, introducing a Point class. The amount of garbage Minecraft made went up very quickly as a result and it got slower.
There were a bunch of other glaring problems ... the fact that Optifine is able to improve it so much shows, I think, that the developers didn't fully understand Java performance.
The poster was commenting on the maintainability of the C++ code. Unfortunately, poorly written/structured code can still be as performant as well designed code.
As for your C++ vs Java question... put very simply, C++ will be faster than languages like Java when it comes to graphics and any software that is close to the hardware.
That's what I figured on both accounts. I guess I'm just bothered by the obvious inefficiency of Minecraft versus practically any other Java game I've played. Even other Java-based voxel games have far better performance.
I was keeping it high level because the person asking the question is a non-programmer. To your point though, I should have prefixed "correctly written" in front of C++.
> I was keeping it high level because the person asking the question is a non-programmer.
Well, I should have been more accurate: I'm not a programmer by trade, but I do understand the basic concepts of computer programming, and I've dabbled with both high level and low level languages. I've even done some assembly programming in the distant past, about 20 years ago, just to learn it, as well as a stint with SQL/400 on the AS/400 about 14 years ago. But these days the closest I come is bash scripting or dabbling in Python or Lua. I've never messed with C/C++ or Java though, hence my questions directed at those languages.
You're comparing today's Minecraft with all the bells and whistles to Minetest. The original comment about trying to extend it in C++ compared to Java is perfectly valid. It's why Java rose to power and remains. It's why it takes so long to roll out new features in the Windows 10 Minecraft client (which is basically the PE client).
It's worth noting that Minetest is available on Ubuntu (and possibly Debian?) via apt (apt-get). Not sure how dated it may be, but it's still playable and useful.
As a longtime MC user, I have to say this is really cool. OTOH, it doesn't have MC's amazing mod ecosystem, which is a huge part of why that game is so great.
It doesn't have as big of a modding ecosystem as Minecraft, simply because it doesn't have even a fraction of the community, but apart from size, I don't think I would agree on its modding ecosystem being less amazing.
Minetest has for one a stable modding API, meaning that mods generally don't break left and right with each release. If you find a mod, chances are that it's going to work, even if it hasn't been maintained for a while. The whole game content itself is also built using this modding API, meaning that there's nothing stopping you from making mod-content, which has just as high quality as the built-in content. Or you can write your own game completely from scratch. Or you can create mods which have then again other mods as dependencies.
Minetest also has what's probably best described as "Modpack as a Service". When you connect to a server, your client downloads the mods that the server has installed and applies them. This means that you can play on a modded server without making any changes to your client. You can just connect to random servers to take a look at the different mods that exist, without any hassle whatsoever.
This also works in singleplayer, i.e. you can play with different sets of mods on different maps, again without hassle. You just use the built-in mod manager to enable the mods that you want on a per-map basis.
Those are all advantages, but MC's unofficial mod support is very good, and has much of that.
The real problem isn't MT's hypothetical mod support, it's that people aren't building the kind of mods that you get in MC: There's no BC, IC2, AE, TC5, TE4, CC, Ars Magica, Blood Magic, TConstruct, Forestry, FMP, RC, EE3, and so on. Those mods are a big part of why MC is what it so great, and MT can't get away with just copying them: It can copy, sure, but it should also have its own mods, and they should be good ones, because otherwise there's no reason to play it over MC.
It doesn't matter how good your mod support is. It matters how good your modding scene is. And MC has one of the best since HL.
Most mod-heavy games support that, going back to the classics like Unreal Tournament 1. Generally using Lua or some other embedding-oriented language, and minimal security audits. Anything else has a prohibitive workflow, and players won't exactly be auditing the mod-packages they run.
Lua is well-sandboxed for this, but I doubt devs are auditing the entire API they present to Lua.
And no, there are no security audits on engines like this. The only reason the mods havent installed a cryptolocker is because nobody has mad a really concerted effort to do so.
It isn't code is ran by the server and the client only sends information to the server about the current state of the client. This of course is sub-optimal as it can introduce a lot of lag to a game with mods that add vehicles or mobs
Minetest doesn't send mods to the client it only sends information like a list of blocks registered by mods. The client doesn't execute any code sent to it by the server.
Minecraft never got an open source release or official mod support. Mods are made using libraries reverse engineered from the official game, then installed by patching the game. (This is made a bit easier than it would otherwise be because Minecraft is written in Java, but Mojang runs it thru a code obfuscator so unzipping the .jar shows a huge codebase with class and method names like "Ijf8". It's pretty gross.)
MineTest is open source and has modding support as a feature.
The C++ Minecraft implementation (Minecraft Pocket Edition and Windows 10 edition) is getting a fully supported add-on system. They're angle for data-driven entity/item customization (simple JSON files) and C# code for implementing entirely new behaviors and components.
That sounds dumb. Why? because they've built up an ecosystem around an API that they're about to throw by the wayside (unless they integrate it into MCJE), and I very much doubt that the new system will be as powerful (will it be able to handle mod conflicts? What about the very powerful APIs that Forge has built over the years, will you replace them? I'd like to see you try to rebuild Fluid API, FMP, OreDict, FluidDict, and the rest. And if you don't, than the best of modding probably won't be able to be rewritten for your new system). Hopefully, Searge is involved, in which case it's more likely we'll get something decent. Also hopefully, Java MC will just include Forge into MC, or at least support it officially, or something. I don't want all my favorite mods to die.
The panel discussion I linked to was really intersting. I believe they said that Searge (who was on the panel) is the leader of the add-ons effort.
They did say that Java MC isn't going anywhere.
Their stated intent is to make add-ons/plugins as powerful as they can, but there is a limitation in that they want them to be able to work in environments like iOS. Add-ons sre no problem: they're just json data files. They think they'll be able use use C# plugins on iOS, but I'm quite interested to see how they pull that one off.
Regardless, there are 30-40 million players of MCPE who have no modding at all today. This new system is going to be a big step up. even if it is entirely different from the way Java MC is extended.
I personally don't think that Mojang would do that unless forced to, especially given what would happen to the community. Most likely established modders would continue to use JMC as their base, pushing new modders towards doing so, and thus it would continue to overshadow other versions, as the mods really do make the game.
Okay, good. I'm just nervous, especially since they've been doing this stuff for the MCPE codebase, and Java MC has been mainline since forever. Seeing as I'm a Linux user, I'd rather JMC didn't fall by the wayside.
Exactly. Part of what makes MC so great is that there are a lot of high-quality, well designed mods, which all work together to create a really solid experience. MT doesn't have that yet, and the community's small enough that it perhaps never will.
MC's mod ecosystem is also an Achilles heel. The primary audience is tweens/teens and the typical mod author is someone who cranks out something in their spare time and doesn't think about install hygiene. This leads to mods being hosted on the shadiest of shady sites. Downloads can be infected with malware and the users don't really know why they shouldn't just run "InstallMyInfectedMod.exe".
Then there's the mods that break between versions. You can have mod A, B, and C on 1.8.1, but only A and B on 1.8.2 and only B and C on 1.8.3.
Mods to break between versions, which is annoying.
However, the sites are usually MCForum or Curse, neither of which are especially shady, and I've never seen a mod packaged as an exe by its creator. You're probably looking at the cites that host a collection of mods from other sources, which are about as shady as their software equivalents: sites like cnet, etc.
Unfortunately this doesn't seem to expose nearly enough features to the programmer of mods. No way to do direct rendering of your own, add AIs, or many other much needed things.
You can basically just define blocks and HUD items and that's it.
Good work on writing the engine, just needs a little more work on the API side.
--
I just tried reading the code to learn how MineTest does voxel meshing, and it didn't go so well.
(Voxel meshing is about turning blocks into triangles efficiently, and it's surprisingly tricky. Mikola Lysenko wrote a great exposition of the problem and several solutions way back in 2012: https://0fps.net/2012/06/30/meshing-in-a-minecraft-game/ )
I was curious which approach MineTest chose, and I still don't know. I think I found the files where the meshing happens, mapblock_mesh.h/cpp. The code quality is... less than perfect.
There are 200+ line C++ functions. There's commented out code and preprocessor "#if 0" ignored code.
There's a struct that looks important, but it's called "MeshMakeData", and I don't know what it represents. The comment above just says "Mesh making stuff":
https://github.com/minetest/minetest/blob/0a16e53b40d347db7d...
The file that seems to run everything, game.cpp, is almost 5000 lines long.
--
For an example of really clean game code, check out Quake or Doom 3. Both have:
* short and sweet main() methods
* comments that guide the reader and explain what does what
* clean decomposition
* short, readable functions, and...
* reasonably small files
So far, MineTest, at least in part, took the "big hairy ball of C++" approach.
Good luck with future development!