CryEngine out on GitHub
github.com
github.com
From https://github.com/CRYTEK-CRYENGINE/CRYENGINE/blob/release/C...:
// State flags
enum EGlassRNState
{
EGlassRNState_Initial = 0,
EGlassRNState_Weakened = 1 << 0,
EGlassRNState_Shattering = 1 << 1,
EGlassRNState_Shattered = 1 << 2,
EGlassRNState_ActiveFrags = 1 << 3
};
Als a C# dev, I write Enum flags from time to time, but I always just write out the values; never thought of using bit-shifting to prevent typos :)#define BIT(nr) (1UL << (nr))
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#define BITS_TO_TYPE(nr, t) (((nr)+(t)-1)/(t))
You're making it clear these are flags and you're concerned with individual bits. 2, 4, 8 etc. are decimal numbers and mean something else i.e. "two", "four", "eight".
Does bitwise ORing the decimal numbers 2 and 4 really make sense? Not particularly, but combining bits at certain offset does.
// State flags
enum EGlassRNState
{
EGlassRNState_Initial = 0,
EGlassRNState_Weakened = 1 << 0,
EGlassRNState_Shattering = 1 << 1,
EGlassRNState_Shattered = 1 << 2,
EGlassRNState_ActiveFrags = 1 << 3
};
foreach(var val in Enum.GetValues(typeof(EGlassRNState
)))
{
Console.WriteLine($"{val} -> {(int)val}");
}Output:
EGlassRNState_Initial -> 0
EGlassRNState_Weakened -> 1
EGlassRNState_Shattering -> 2
EGlassRNState_Shattered -> 4
EGlassRNState_ActiveFrags -> 8 writable = 001
readable = 010
readwrite = 011 (writable | readable)But it's also still in the process of Shattering, so when I jump through it, I'm risking cuts, it's actively producing noise for someone to hear, that laser I'm shining at it will be fragmenting wildly rather than reflecting off/passing through/deflecting like it was before the glass started Shattering.
Anyway, I don't think it's worth arguing design on this codebase because it is full of dirty things.
e.g.
EGlassRNState allowed = EGlassRNState_Initial | EGlassRNState_Shattered;
EGlassRNState current = EGlassRNState_Initial;
...
[DayOfMonth(28)]
D28 = 134217728L,
[DayOfMonth(29)]
D29 = 268435456L,
[DayOfMonth(30)]
D30 = 536870902L,
[DayOfMonth(31)]
D31 = 1073741824L,
[DayOfMonth(DayOfMonthAttribute.LastDayOfMonth)]
Last = 2147483648L
Vs ...
[DayOfMonth(28)]
D28 = 1 << 28,
[DayOfMonth(29)]
D29 = 1 << 29,
[DayOfMonth(30)]
D30 = 1 << 31,
[DayOfMonth(31)]
D31 = 1 << 31,
[DayOfMonth(DayOfMonthAttribute.LastDayOfMonth)]
Last = 1 << 32
Hint: It's with D30 in both cases...I might be a bit weird, but I know the powers of 2 up to 2^20 in decimal. They've just snuck in there over the years, along with 2^24 and 2^31. So if I need some powers of two I might well just type them out like that. I can recognise a few common combinations too... it is all much easier in hex though.
I should really get the full set up to 2^64 memorised...
FIRST_FLAG = 0x00000001
SECOND_FLAG = 0x00000002
THIRD_FLAG = 0x00000004
FOURTH_FLAG = 0x00000008
FIFTH_FLAG = 0x00000010
SIXTH_FLAG = 0x00000020
SEVENTH_FLAG = 0x00000040
EIGHTH_FLAG = 0x00000080
NINTH_FLAG = 0x00000100
...
28TH_FLAG = 0x08000000
29TH_FLAG = 0x10000000
30TH_FLAG = 0x20000000
Of course, I've never needed more than 12 bits of flags concurrently.
EDIT: Bleh, it wiped out my white space. These should be aligned.
But really, I've only used this with two or three character hex codes, so it works out much better. 0x01 through 0x80 are pretty hard to mess up, and 0x001 through 0x800 isn't bad either.
But yeah, the bit shifting honestly is probably a better solution. Cleaner, more scale-able.
If you don't care about backward compatibility (i.e. the flags are used internally and never written anywhere), then a better method is actually to grab the value one line above and bit shift it by one. That way you can insert values in the middle and you won't have to change every single line (just two).
Honestly, flags should be a type. IIRC, the C# designers have admitted this was a mistake on their parts to continue C's ambiguity between flag enums and choice enums.
type
EGlassRNState = enum
EGlassRNState_Initial,
EGlassRNState_Weakened,
EGlassRNState_Shattering,
EGlassRNState_Shattered,
EGlassRNState_ActiveFrags
proc hasGlassShattered(mState: set[EGlassRNState]): bool =
EGlassRNState_Shattered in mState
proc hasActiveFragments(mState: set[EGlassRNState]): bool =
EGlassRNState_ActiveFrags in mState
assert hasActiveFragments({EGlassRNState_Shattered, EGlassRNState_ActiveFrags})Edit: I was mistaken, it still requires manually setting the numbers, it just adds neater ToString support: https://msdn.microsoft.com/en-us/library/system.flagsattribu...
type EGlassRNState int
const (
EGlassRNState_Initial EGlassRNState = 1 << iota
EGlassRNState_Weakened
EGlassRNState_Shattering
EGlassRNState_Shattered
EGlassRNState_ActiveFrags
) def makeflag():
flag = 1
while True:
yield flag
flag = flag << 1
flag = makeflag()
E_GLASS_RN_STATE_INITIAL = next(flag)
E_GLASS_RN_STATE_WEAKENED = next(flag)
E_GLASS_RN_STATE_SHATTERING = next(flag)
E_GLASS_RN_STATE_ACTIVE_FRAGS = next(flag)
flag2 = makeflag()
UNRELATED_FLAG = next(flag2)
UNRELATED_FLAG = next(flag2)
Also no chance of fatfingering a number. >>> _bitflags = [1<<i for i in range(128)]
>>> (E_GLASS_RN_STATE_INITIAL,
... E_GLASS_RN_STATE_WEAKENED,
... E_GLASS_RN_STATE_SHATTERING,
... E_GLASS_RN_STATE_ACTIVE_FRAGS,
... *rest) = _bitflags
>>> E_GLASS_RN_STATE_ACTIVE_FRAGS
8From the language spec:
const ( // iota is reset to 0
a = 1 << iota // a == 1
b = 1 << iota // b == 2
c = 3 // c == 3 (iota is not used but still incremented)
d = 1 << iota // d == 8
)Seems bizarre. That's actually a pretty confusing idiom in that context.
org/bitflags/bitflags/macro.bitflags!.html is much better.
To save you guys two clicks.
enum MyEnum
{
MyEnum_Foo = 1 << 0,
MyEnum_Bar = 1 << 1,
MyEnum_Baz = 1 << 2,
MyEnum_Quux = 1 << 4,
MyEnum_Xyzzy = 1 << 8
};
:)I believe that's what they meant. I worked in C# for many years, and many, many places wrote out bit masts in base 10 literals as no one realized they could just left-shift. Similarly, whenever I would use the ?? (null-coalescing) operator, the reviewer would inevitably point out my "syntax error", at which point I'd have to point them at the ~10th page of the nearest C# book to convince them that, yes, that is one of the valid operators -- and it's quite useful too!
Man, do I miss those first years of my career working in .NET -- dunno why I ever switched to OSS stuff.
I suppose this is the result of deadlines and lax code reviews.
This is usually the result of years of changing/updating the code. Any living code base tends to grow and accumulates cruft over time. Just because it doesn't fit the ideal you learned in university doesn't mean it is bad code, this is real life code.
There is no excuse for not writing well commented code - or even code with well named variables and functions that reduce the need for as much commenting.
If you suffer from code like this in your workplace, perhaps actively comment it as you reach an understanding of what it does.
"I've worked in the Games industry with age old engines, I currently work in embedded development with a code base over 10 years old - I'm fully aware of what "real life" code is like. There is no excuse for not writing well commented code - or even code with well named variables and functions that reduce the need for as much commenting. If you suffer from code like this in your workplace, perhaps actively comment it as you reach an understanding of what it does."
Relatively experienced 6 year C++ dev - I mainly mentioned university because things where much stricter - but having an environment with decent code reviews and maintaining a little self discipline goes a long way with the sanity of your co-workers.
6 years is significant, but it's not a long time. There's much to learn, particularly about the cultural aspects of various segments of the industry.
This is excellent code that was produced on a tight timeline.
*Edit - Yes though - by no means do I think I'm some big shot know it all. But I do have strong feelings about readability after having had to deal with code which is awful to grok.
To clarify, my objection was that we're criticizing this code for superfluous reasons when it's currently a delicate political climate in most game companies to even release code like this in the first place. It's probably best not to imply their reputation should be harmed by their lack of comments, since this can discourage other game companies from releasing their code in a similar manner. I've seen the argument "it might harm our reputation" be used to block endeavors like this.
I really hope that companies don't view criticism as a negative thing, it's cause for discussion and change which are most certainly positive - I hope some bugs are found and they start to feel the benefit of the community a little.
Using raw pointers in C++ is rarely really needed.
Shared pointers (as in ref counting) is just an example of that, so I understood the above comment as implying that game development somehow encourages manual pointers management. May be I just understood the intention wrong, and it didn't mean to exclude other types.
More info on performance loss due to cache thrashing:
https://lmax-exchange.github.io/disruptor/
https://lmax-exchange.github.io/disruptor/files/Disruptor-1....
http://martinfowler.com/articles/lmax.html
http://mechanical-sympathy.blogspot.com/2011/08/disruptor-20...
And http://mechanical-sympathy.blogspot.com/ is great in general.
The reason that raw pointer management works in gamedev is because gamedev is closer to crafting than traditional programming. No one will die if a game crashes, and the iteration loop is a tight feedback cycle of code-compile-run code-compile-run.
Due to the nature of the entertainment industry, the codebase also loses much of its value within a year of releasing the game, as opposed to traditional software that typically gains value with time, meaning it's more important to get code out the door than to get it right. History is littered with the skeletons of game companies that disregarded this unfortunate truth.
The reason this works is because of discipline. Generally, there is a FooManager class which owns Foos. The FooManager is responsible for both allocating and deallocating Foos, regardless of where they're used. And in a game, "When should something be deallocated?" usually has a clear answer: When the level loads, for example, or when you move from one part of the continuous world to another part.
Then there are Subsystems (singletons) for each division of the engine: GraphicsSubsystem, InputSubsystem, etc.
Between those two patterns, there aren't a lot of ways to lose track of a pointer.
So limiting lifetime of the object by some scope should work pretty well for it, and if you can pass raw pointers to transfer ownership, you can as well pass managed ones. At least it's safer.
Anyway, by using something like Rust a lot of such problems are solved by the language itself.
I don't know where Rust came from, since the discussion was about C++. But feel free to write an engine in Rust. It seems like a promising approach.
I think another important factor is the pseudo-realtime update loop that synchronization is tied to.
Unless there is some garbage collection between game state changes (unloading unused resources during a level, etc...), its rare that references are invalidated unexpectedly, or accessed in parallel to the cleanup step between game state changes.
eg. a global state change from RUN to CLEANUP tells the subsystems to stop using a resource, so during the CLEANUP state the subsystems can safely delete any resources they have ownership of.
The more time I've spent understanding and building game engines, the more I see it as an organised network of state-machines managing and working with collections of data.
More often than not, shared state has clear ownership and lifecycle management built into the relevant state-machines. By isolating creation and destruction of resources in the transitional states (load and start a level, open a menu, change to Game Over screen), most of the code can safely reference data from other subsystems without reference counting, under the assumption that references are only valid until a global, shared transition in state.
Imagine a player entity that stores a reference to a model, texture, sound effect, input state, etc... If that data is loaded at the start of the level, and destroyed when the level ends, is there really a need to inc/dec a reference count if an enemy entity shares a sound effect reference?
Long functions which have grown over time are also understandable, given the realities of changing requirements and such.
Thousands of lines of uncommented code, however, are not understandable... in the sympathetic sense, or literally.
Real-world work stresses getting stuff done. And in this case parts of the code can also take a life of their own.
Ideally both ideologies meet somewhere in between and you get code that works and is maintainable. But sometimes you can get bad code that is shipped... or an unhealthy obsession with polished code that never ships. One is infuriating, the other makes businesses slowly unfeasible.
Frequently changed parts of the code were a hideous mess of 90% comments to 10% code. And then occasionally we'd just rename an entire file by prepending 'old' to it and starting fresh with a new file.
That place was such a learning experience on the concept of technical debt. But at least I got a fun talking point for my resume. "x++, is that a typo?" "No, sir..."
This is a great piece of advice and one that has worked for me in the past when refactoring code like the one referenced.
Nicely put. :) Thanks for the link.
I was quite surprised at how often copy-paste-modify
operations resulted in subtle bugs that weren't
immediately obvious.
I now strongly encourage explicit loops for everything,
and hope the compiler unrolls it properly.
I found this particularly interestingAnother good example of this is the Phong shading model. IIRC it was invented in the mid-70s, and some software rasterizers implemented it, but it didn't really make its way into graphics cards with fixed pipeline rendering until the mid-90s.
Graphics tech in the 90s and even early 2000s involved a lot of hardware and software catching up to theory from the 70s and 80s because we were finally getting enough compute power to make it worthwhile to use "approximate" rasterization-based algorithms in order to get real-time rendering.
> Did you think about doing a first-person shooter after their success with Wolfenstein 3D and Doom?
> TS: It was funny how we got to that point. When I saw Wolfenstein for the first time, that was truly shocking. I'd never envisioned that you could do 3D in a computer game; I don't know why.
> The research had indicated that you could do that for at least 15 years before that, but it was this 3D game with real-time texture mapping; you know, real-time bitmaps scaled up and displayed in 3D on the screen. It never occurred to me that you could actually write code to do that. It was just another lack of foresight there.
> But seeing that for the first time, I was like, "Wow, I'm totally not worthy. I need to get out of programming now, because I'm never going to be able to compete with this." So they just basically demoralized me into becoming a manager for a few years.
> Around 1994, James Schmalz had written this 3D texture-mapping code, and I was starting to think, "Hmm, maybe that's not so hard." So I started reading up on references there and experimenting with it, and it turns out that, yeah, it's just another piece of code that you can learn how to create.
http://www.gamasutra.com/view/feature/4035/from_the_past_to_...
The algorithms themselves (like 3D texture-mapping) are college third year problem set level difficulty to actually implement, but having the curiosity, courage, and ambition to be the first to do it real-time is huge!
The algorithms used in today's 3-d game engines are definitely more complex than something I'd expect a college student to do, but the state of the art has also progressed substantially since the 90's.
The man is a legend. I remember using his little set of DOS utilities (things like stuffit.com [2]) back in the early 1990s, which I got from a friend whose dad was a colleague of his at Hydro. They were all written in assembly language, and were superb little extensions to DOS.
[1] https://www.linkedin.com/in/terje-mathisen-b740181
[2] http://files.mpoli.fi/unpacked/software/dos/utils/keyboard/s...
Needlessly increased variable scopes - and thus increased risk of harder to follow cross-dependencies - is probably the biggest downside risk. But I've found code that executes linearly easier to read and understand when it's written linearly. When everything is factored into functions - particularly impure functions - you need to click all over the place to understand the whole.
If there are higher-level primitives that can be used - filters, maps, folds, etc. - then they can reduce the verbosity overall. Some monadic styles can flatten nested code by computing a pipeline / computation rather than having lots of nested loops. But depending on the language and the problem domain, performance may suffer.
I refactor as soon as my code gets past 3 levels, I don't know how one is supposed to readily understand this block of code.
The lack of comments isn't what troubles me. Comments get old and, when they do, they get completely misleading and downright dangerous. As soon as you feel the need to add a comment, it's often because that particular chunk of code should be extracted into its own function/method/whatever and given an intelligent name. Comments should be reserved for really important stuff, like when the code does something totally non-obvious.
generally agree on commenting, but it's also about discipline - method-level commands are rarely updated, but if there is some particular algorithm within method, I don't see a reason to describe it beforehand on a line or two.
General rule - if method is longer than my screen, it's time to refactor. very rarely this isn't a good idea.
http://hg.icculus.org/icculus/lugaru/file/97b303e79826/Sourc...
Question regarding index access: There are tons of for loops with player[k] occurrences and similar. Personally I would create a local variable and prevent further index-retrievals.
Is this worthwhile or would a compiler optimize the array-index access away? Or maybe subsequent uses of the same index are cached by the cpu? Does someone know?
One reason you might want to use a separate variable would be to prevent indexing mistakes, like using i instead of k by mistake in a context where i is a nested loop's counter. But apart from this and other "to make it easier on the human" reasons, there's no point in caching that in a variable. Now, if you were writing Python on the other hand...
Grabs the eye bleach
What can be the rationale behind writing this [1] ?
[1] https://github.com/CRYTEK-CRYENGINE/CRYENGINE/blob/release/C...
Consder this:
char* p1, p2;
You could erroneously think that char* is a type, and p1 and p2 are variables of that type. That's not correct however, since p1 is indeed char*, but p2 is char. Such declarations therefore should be strongly avoided for clarity.[1]: https://github.com/CRYTEK-CRYENGINE/CRYENGINE/blob/release/C...
So I always do char \p1. Yes, for a non-C programmer its not as intuitive, but C isn't intuitive a lot of the time (cough, char p1[] what?). But you avoid making these mistakes altogether.
Note in function declarations I use char, because you cannot do statement expansion with a comma there, and because in headers the variable name is optional anyway.
char *p;
?I prefer to use char* p; as well as std::string& s; and etc. rather than attaching the type syntax to the name, since in essence that's part of the type. But yes, it's a mess that this inherited C logic doesn't treat it that way clearly. To avoid such mistakes, it's better not to use comma declarations altogether, you can perfectly avoid them.
It's a good feeling when working with new languages like Rust which avoid such mess.
The point is, though, that while in a developers mental model you attach ref or ptr to the type, the language itself does not, and writing it out like it does can easily drive newer developers who do not understand the nuance to make hard to recognize mistakes as a result of it.
Basically you pay whatever you want, if you want, and have a choice of how much of that goes to the developers and how much goes to an Indie Fund that we use to fund indie projects that use the engine.
We also offer "Insider Memberships" (https://www.cryengine.com/get-cryengine/service-packages) for studios that want some closer support from us, trainings, etc.
Because I really like this pricing model (and your engine) and I hope it will become standard over time ... but at the moment unfortunately it isn't and still too many people and companys won't pay anything if they don't have to. So good luck to you.
"use the CryEngine for the development of any Games which are harmful, abusive, racially or ethnically offensive, vulgar, sexually explicit, defamatory, infringing, invasive of personal privacy or publicity rights, or in a reasonable person's view, objectionable;"
given that politics tends to be much more qualitative than quantitative, it's unclear that any "political disagreement" can be anything other than "subjective".
Note: I'm just as horrified as you about that clause but it's in every CC license AFAICT
When you review the license, it is really not like this. Only games made explicitly for "entertainment purposes" can use the engine -- even "Serious Games", which I guess means games that may straddle any actual utility, are not allowed. Most likely Kerbal Space Program would be considered excessively "scientific" and not allowed to use CryEngine.
There's also a very scary clause that essentially says "if we don't like your game we can classify it as objectionable and withdraw your license".
This is a cool release from an academic standpoint, but should probably not be used by real people for real projects with the license as-is. There are many excellent truly open-source game engine options.
i'm not sure what you mean by "truly open-source"; what "game engine options" are you referring to?
Software distributed under a license approved by the OSI. These licenses, as far as I know, place no limitations on the type of speech that can be produced with licensed software. To use CryEngine, the people who work at CryTek must not find any of your project's content "objectionable".
>what "game engine options" are you referring to?
http://irrlicht.sourceforge.net/
http://www.garagegames.com/products/torque-3d
https://github.com/id-Software
and many others; I'm sure there are big lists floating around. All of the engines listed here can be used even if the authors of the engine disagree with what you want to say, and I believe they've all been used in real, honest-to-goodness commercial games.
Irrlicht and Torque is good options for small indie games (actually there many more great engines for small games), but they still can't be compared with "big" commercial engines.
Oh and thanks for all your hard work, I've learned a lot from you guys over the years!
In other words, fully and officially support blender :)
In other words fixing the art pipeline needs to be an offical, fully supported endeavor. Which is why I asked.
"CryEngine is a game engine designed by the German game developer Crytek. It has been used in all of their titles with the initial version being used in Far Cry, and continues to be updated to support new consoles and hardware for their games."
which I found on wikipedia after clicking through 3-4 pages. General consensus seems to be that it is pretty awesome though, so keep up the good work.
https://github.com/CRYTEK-CRYENGINE/CRYENGINE/blob/release/C...
What was the purpose of tamagotchis?
We may never know.
But we can breath a sigh of relief that whatever it was, we beat them in the end.
If you're a student using CryEngine you're probably not worth suing for copyright infringement (at worst a C&D maybe). If you're a corporate entity who is distributing a game which licenses CryEngine, you certainly may be worth suing for infringement.
There are restrictions on Serious Games, but amusingly a Serious Game isn't a game.
I'm thinking of things like Starfighters.
[0] 2.2. If you are a student or a member of an academic institution you are in addition entitled to develop Serious Games using CryEngine and to render such Serious Games in object code form (including the CryEngine Assets and the CryEngine Redistributables) pursuant to the CryEngine documentation. However, you are in no case entitled to commercially exploit such Serious Games without Crytek’s explicit prior written approval.
What I'm getting at is that this isn't the worst license from a commercial-first software distributor.
Maybe I miss something, but you literally said that they didn't allow one to build GPL software.
But I cannot find a version of the first (2001 or 2002) EULA, so it's possible my memory isn't exact.
Edit: All I could find https://yro.slashdot.org/story/02/08/04/132221/more-ms-eula-...
https://wiki.wireshark.org/Development/MSVC7
About a paragraph down that page, it mentions the concept of Visual Studio 2003 not being allowed to compiled GPL code, stating that's a misconception.The original EULA doesn't seem to be online any more though, so it's hard to tell.
http://www.microsoftvolumelicensing.com/userights/Downloader...
> Potentially Viral Software. Your license rights under Agreement and/or Academic Agreement are conditioned upon your compliance with the following terms: You must not: (a) Integrate or otherwise incorporate Potentially Viral Software into, or combine Potentially Viral Software with, any Licensed Product, Software Documentation, or derivative work thereof; (b) distribute Potentially Viral Software in conjunction with any Licensed Product, Software Documentation, or derivative work thereof; or (c) use Potentially Viral Software in the development of any derivative work of any Licensed Product or Software Documentation. “Potentially Viral Software” means software which is licensed pursuant to terms that directly or indirectly (i) create, or purport to create, obligations for Microsoft or our suppliers with respect to the Licensed Products; or (ii) grant, or purport to grant, to any third party any rights or immunities under Microsoft’s or our suppliers’ intellectual property or proprietary rights in the Licensed Products. Potentially Viral Software includes, without limitation, any software that requires as a condition of use, modification and/or distribution of such software that other software incorporated into, derived from, or distributed with such software be: (a) disclosed or distributed in source code form; (b) licensed for the purpose of making derivative works; or (c) redistributable at no charge.
I'm not a lawyer, but this term sounds scarier than I think it is. "Potentially Viral Software" is defined to be software under a license that places obligations on Microsoft (which would be every license offered by Microsoft, and no license not offered by Microsoft, so as its only effect is to prevent you from using Microsoft software, it seems an unintelligible term). It goes on to say this "includes... software that requires... [being] distributed in source code form" but that has nothing to do with "Potentially Viral Software" as defined just before.
My gut says Microsoft wrote this term in a manner calculated to confuse drive-by software engineers into believing that VS can't be used to compile GPLed software, that the GPL creates obligations on third parties, or both.
What I believe you misunderstand is that "the aim" or "the whole concept" of an EULA is not to explain things clearly to end users. On the contrary, "the aim" of an EULA is to offer terms that are favorable to the licensor (and thus unfavorable to the end user), and this aim is best accomplished when the user does not especially comprehend the document. In other words, "the aim" of an EULA is to be obfuscatory.
Anyone who wanted to use a standard document has many options to choose from that are probably familiar to you. ISVs who have passed over the ten-or-so standard texts that you are familiar with will not be convinced by an eleventh.
I've read Apache2 and GPL2 licenses and I can't say I comprehend them fully. Read the liability clauses in GPL and Apache licenses and compare them to MIT or BSD.
It is the same for the law. Even the basic "email-grade" legal problems are actually very complicated, and it is no good trying to simplify them down to a lay level. I'll defer to Lawrence Rosen on this, from his book Open Source Licensing: Software Freedom and Intellectual Property Law:
> The same programmers who cringe when a lawyer attempts to write high-quality software feel no qualms about writing their own open source licenses. Their goal, it appears, is to craft something that sounds like a license, to define a form of software freedom with reasonable terms and conditions, and then wait for the community to adopt the license and distribute software under it. This technique sometimes works. Some members of the open source community are more concerned with mak- ing a philosophical statement, getting free software distributed to the world, and letting license enforcement take care of itself somehow in the future. That can be a commendable goal, but from a lawyer’s perspective, it is amateurish and risky.
The reason that BSD/MIT seem readable to you is actually that they lack a lot of clarity on important points. For example, they say nothing at all about patents, which is the primary type of software litigation today. So an Oracle-type could offer you software under an MIT license, and then turn around and sue you under patent law for using the software they offered you. Whether they would win is an interesting question, but we will not find out because you will settle.
Meanwhile, Apache2 or GPL3 or other post-1970s licenses have actual clauses to deal with this. So now your lawyer can print out the license, highlight a sentence, scribble "SEE?" below it, add "Respectfully submitted, John Smith Esq." at the bottom and that is the end of your lawsuit.
You can still use the src to investigate bugs in source code and walk-around them in your product.
Does this also mean that flight simulators cannot be written on this engine? I used to play a lot of those for fun, but that could fall under "serious software".
They of course have no reason to use permissive licensing too since that would mean someone else can make money off it.
Unfortunately companies that developing game engines not going to benefit from copyleft licensing since there is no demand for GPL from real game developers. After all there is very few open source games around and only bunch of them aren't clone of something else. Probably none of these projects ever going to need anything as complex as CryEngine: there is enough of good open source engines for indie games.
So if they release engine as GPL they simply won't get any more developers in community. At best there will be few incompatible forks made by developers who only want to release changes under GPL.
PS: So just keep in mind that in case of CryEngine "source available" offer appear because it's only way to compete with other commercial engines and make money. They intentionaly keep it proprietary instead of going open source since it's better for their business.
https://wiki.python.org/moin/PythonSoftwareFoundationLicense...
(I Am Not A Lawyer, and all that.)
I think that instead of just linking to the license, they should include a copy of it in the root of the repository and refer to that. It is the proper way to do it.
To me, this is a halfhearted attempt to catch up with Epic and Unreal Engine 4, which has really shown the market how to do things right. I actually look forward to engine updates with UE4, not to mention the increasingly better marketplace content. Also, I am hoping to eventually move over to devving completely on linux...
unity and CryEngine are feeling the hurt, ans struggling to respond.
I do rather think it's a last desperate attempt to get it out before crytek is going bankrupt.
The coding style is very Microsoft-like, which is I suppose not a big surprise given it's DirectX roots. 8-space tabs seems to be the convention (ugh). They use XML for their readable format (which explains a little their slow load times).
The code itself is not very well documented but relatively clear to understand. Overall not a bad engine to learn a few things from but if you're new to Game Engines a lot of stuff will probably seem very complex (check out BreakableManager.cpp).
It's no Quake 3 in elegance but it's got a lot of advanced functionality (especially in the editor). Overall, it's pretty awesome that they released this. Its a huge gift to everyone that is curious what a world class game engine that has shipped a ton of AAA games looks like.
Just in case first CryEngine and early versions of CryEngine 2 had OpenGL renderers, but code style was pretty much the same.
Lumberyard is an immense lock in to the amazon stack with a lot of small print, a huge risk if you believe your game to be worth anything.
CryEngine has (had?) fairly bad licensing terms overall but they're working on them (this OSS strategy is likely part of that) and they are nothing like the Lumberyard terms which essentially buy out your soul.
> 57.4 Operating Restrictions. Without our prior written consent, (a) the Lumberyard Materials (including any permitted modifications and derivatives) may only be run on computer equipment owned and operated by you or your End Users, or on AWS Services, and may not be run on any Alternate Web Service and (b) your Lumberyard Project may not read data from or write data to any Alternate Web Service.
distribute, sublicense or exploit in any other form: the CryEngine (except for the Redistributables), e.g. as a stand-alone development engine; the CryEngine Documentation; the CryEngine Tools; use the CryEngine for the development of any product other than Games, including without limitation: military projects gambling; simulation (technical, scientific, other); science; architecture; pornography; Serious Games.
Serious Games? did lawyers actually even read this?
"A serious game or applied game is a game designed for a primary purpose other than pure entertainment. The 'serious' adjective is generally prepended to refer to products used by industries like defense, education, scientific exploration, health care, emergency management, city planning, engineering, and politics."
https://www.cryengine.com/get-cryengine
I am just wondering how the distribution is, so how many pay 0, how many 10 etc.?
Could imagine that this pricing could lead to higher total revenues than the classical three-prices-page.
(By visiting https://www.cryengine.com/, I found out that it's a game development platform.)
Only has 90 stars ATM which seems odd if it has been up here for a while.
Before it was under perforce, apparently.
2.1. Grant: Subject to strict and continuous compliance with the restrictions of this Agreement Crytek grants to Licensee a non-exclusive, non-transferable, non-assignable, non-sublicensable, limited license (the “License”) only:
[...]
2.1.2. to develop, maintain, extend and/or enhance CryEngine pursuant to the CryEngine Documentation;
Edit: What I mean is that the implementation of C++ classes seems to be in header files and I'm wondering if this is a common way to do things at game studios.
Found cpp files, but it's interesting that so much of the class implementations are directly in the headers.
In another file[1] it seemed to make more sense (getters and setters, along with a smallish class where I guess you didn't want to bother making a new file).
[EDIT] Could I also ask why you have defined some very large classes entirely in the cpp files[2]
Also, thanks for this, very interesting to read the source for other large projects.
[0] https://github.com/CRYTEK-CRYENGINE/CRYENGINE/blob/63418e7c9...
[1] https://github.com/CRYTEK-CRYENGINE/CRYENGINE/blob/63418e7c9...
[2] https://github.com/CRYTEK-CRYENGINE/CRYENGINE/blob/63418e7c9...
You might put function definitions in headers to (1) avoid linking a library (2) explicitly declare a function as inline, maybe (3) it's simple enough that you don't lose readability by inlining it.
The one about putting large classes entirely in CPP files: I wouldn't do it this way for readability reasons, but putting it in the CPP file directly does restrict anybody else from using what is supposed to be a one-off helper class. I think that's the intent here.
Maybe this is their attempt to have the community fix it for them =)