SimCity UI Code + DRM
gist.github.com
gist.github.com
Just a reminder that I (and some others, hopefully) are in ##closure-tools on Freenode to help you out if you have questions. Make sure to stay in the channel if you ask, as it's low-volume. I don't believe I've let a question go unanswered in well over a year, unless the person left right away and there was no point in answering it.
The channel itself is in no way affiliated with Google, nor am I.
(Before you say "The UI, obvs", I'm wondering if it's a common practice to write UI code in games in javascript. I know that Gnome has a lot of JS that's tied into UI, I didn't expect the practice to make itself into game dev).
And if this code is actually from SimCity, does SimCity have some type of v8 or other js engine packaged with it?
[1] http://documentcloud.github.com/backbone/#examples-battlefie...
It's becoming more common. Libraries like Awesomium[1] make it trivial to render browser content to an in-game texture and the V8 engine, while not 'easy' to integrate, is quite empowering in that you can have the UI code call directly into your compiled code.
>does SimCity have some type of v8 or other js engine packaged with it?
Very probably. Most games have some scripting layer in their engines to simplify implementing non-performance-critical game logic. Lua and JS are two of the most popular languages for achieving that these days.
We switched to using Chromium Embedded 6-8 months ago and haven't regretted it a bit.
[1] http://www.insomniacgames.com/new-generation-of-insomniacgam...
Does anyone have any experience / is Chromium Embedded any better than using the WebKit component that is part of Qt 5.0 (QtWebKit)? Both seem to use same JavaScript engine (V8) and it seems that using QtWebKit in headless browser scenarios in Linux environment seems to be a bit easier, but I'm kind of wondering why there seems to be more buzz around CE than QTWK. On obvious reason of course is that using QTWK in app "forces" you to use Qt in other parts of the app that can be a good / bad thing depending on the details.
Q: Is the launcher built on WebKit or some other layout engine? Are there things in game that are WebKit too?
A: The whole UI is done in javascript running a custom version of webkit. :D
I'm not a fan of DRM or what they did to Sim City... I've also got nothing against reverse engineering, excerpting code snippets, and that sort of thing. But violating the terms of GitHub, in addition to someone's copyright? Not cool.
Its uploaded in a nonprofit way, for educational purposes. It is a very small portion of the complete work. The effect of the use upon the potential market is either small or non-existant.
That is three out of the four-factor balancing test regarding fair use. If we guess that this is about 0.3% of the complete work (3MB of a very very large final product), that would be comparable to use 30s clip of a film.
Fair use is meant to preserve access to copyrighted works by the public that granted copyright in the first place--to maintain certain rights for the public and to ensure that any works built upon copyrighted works (whether that's through inspired creativity or just commentary on the original) aren't themselves held hostage by the original copyright holder.
Nothing in this example is transformative of the original work. The poster just released something that somebody else holds the copyright to. The educational aspect is an extremely weak argument; something merely existing in front of your eyes is not educational. The classic take on educational fair use for this would be taking minimal samples from the source and providing commentary upon them (why they did something the way they did, how they solved a problem that plagues a lot of developers, etc).
It's also certainly not a minimal sampling of the material. The code has been minified, but there appears to be a substantial portion of their UI code intact here, and I wouldn't be surprised if it is largely functional without much more work. It would be dishonest to compare 3MB of scripts to a final game including assets, and even with substantial commentary and insight added to the code, you would not be able to justify redistributing this amount of the source. Again, it isn't quoting from a larger source, it's providing the entire source for large portions of the game engine.
IP law aside, I feel the same way about this as I imagine I would have felt if the Doom 3 source had leaked early: no, you won't be able to play the game for free with it, and it is cool to see, but it's shitty that the people that actually wrote it had no say in its release.
While github is often used as a publishing tool, it is also commonly used as a place where work-in-progress is placed. Thus, if someone wanted to create a commentary about a piece of copyrighted material (say, the DRM part of a game), I would personally consider copying the related code into a github repository for refinement to be fair use. So long the four-factor balancing test is fulfilled, why limit the available tools? Should the workplace where such refinement is taking place be limited only as private repositories where each party has a copyright license?
I would also like to note that nowhere in the law does it say that fair use must minimize their usage of the copyrighted work. The law says under its four-factor balancing test:
the amount and substantiality of the portion used in relation to
the copyrighted work as a whole.
How it is interpreted has changed widely in the last 15 years. Some talk about the minimal necessary amount for his or her intended use. Other talks about "the heart of the work". For a time, De minimis was considered, through was later reversed in 2005. var COMPILED = !0
goog.DEBUG = !1
As you would expect in a weakly-typed C-style language, !0 == true, and !1 == false. JavaScript has first-class booleans, and there's not much to be gained by using one of these expressions instead of the literal it evaluates to. It only serves to save character count.Here's another example. Starting at line 91, you get the following:
!COMPILED && goog.ENABLE_DEBUG_LOADER && (goog.included_ = {}, goog.dependencies_ = { // ... and so forth
The above code uses commas in a particular way that usually means it comes from a minifier. JavaScript has a comma operator, which is basically just a statement separator, but it has the interesting property that it joins two statements as a single expression. As in many C-style languages, control flow operators like if and while don't require curly braces, and apply to the immediately following statement if they are absent. The combination of these two means that if(!foo){bar();baz();qux()}
is equivalent to if(!foo)bar(),baz(),qux();
which is shorter by a single character. Because the line of code joined by commas is now an expression, this also lets us abuse the short-circuit property of boolean operators, re-writing the above like so: foo&&(bar(),baz(),qux());
for a further savings of one more character.You pretty much never see the comma operator in code written by humans, because it's not useful for anything. Seeing them in production code, especially the way shown above, almost always means the code came out of a minifier. That actually broke the Opera browser a few months back--apparently the parser ran out of stack space when handling a single expression consisting of over 1,400 comma-separated statements.
fireToken : 1 === f.tradeTokens.data.fireToken ? !0 : !1,
Why might that be a desired output from a minifier? Why not simply fireToken : 1 === f.tradeTokens.data.fireToken,
[1] https://gist.github.com/anonymous/5133829#file-simcityui-js-... fireToken: f.tradeTokens.data.fireToken === 1 ? true : false
In my company I see JS code like the following: if (!!someFlag) { /* ... */ }http://telemetry.simcity.com/simcity/rest/user/1 - user ID 1
http://telemetry.simcity.com/simcity/rest/user/1/friends - their friends
but I thought friends can only seem to see each other on their respective server region. this seems to be storing centralized data?
playing around with other nouns...
http://telemetry.simcity.com/simcity/rest/region/1 - even includes some of their S3 URLs.
http://telemetry.simcity.com/simcity/rest/box/2 - seems list CITY and REGION
i'm trying to think of other nouns to throw in there.
http://telemetry.simcity.com/simcity/rest/user/1027/regions - a list of user ID 1027's regions
http://telemetry.simcity.com/simcity/rest/user/10278/regions - this guy has 4 regions!
(I love RESTful services)
Lots of nice references to cheats though! They all rely on simcity.DEBUG being true,
if (simcity.DEBUG)
switch (a) {
case scrui.kKeyCodeDigit1:
c && (e && !d) && scrui.RunCheat("scgameui -unlockalltools");
break;
case scrui.kKeyCodeLetterW:
c && (e && !d) && simcity.CreateUnit("T_RCI_AddHourlyIncomeCheat")
}
Also pretty nifty: There's a rest api built into the game for communication, (as wel as websockets) and the name and email of one of the programmers are still in the code. simcity.TutorialFakeUserData.creator = {
uri : "/rest/user/0",
tutorialState : 1,
id : 0,
screenName : "Chet Keno",
email : "mayorkeno@simcity.com",
nucleusId : 0,
lastLogin : 0,
isOnline : "true",
avatarImage : "Graphics/Tutorial/tutorial_avatar_keno.png",
cities_count : 1
};
Also interesting is that it seems that this is not just a stripped v8 engine. There's things in the code that make me think the whole game UI is actually a pretty decent webkit engine: simcity.gEventManager = new simcity.cEventManger;
simcity.gEventTypes = {
CLICK : "click",
MOUSEUP : "mouseUp",
MOUSEDOWN : "mouseDown",
MOUSEOVER : "mouseOver",
MOUSEOUT : "mouseOut",
ITEMSELECTED : "itemSelected",
KEYUP : "keyup",
KEYDOWN : "keydown",
DATACHANGED : "dataChanged",
HASHCHANGED : "hashChanged",
GENERICEVENT : "genericEvent",
SOCKETEVENT : "socketEvent",
SOCKETCONNECT : "socketConnect",
SOCKETDISCONNECT : "socketDisconnect"
};
simcity.SocketManager = {};
simcity.cSocketManager = function () {
this.mSocketListeners = [];
this.mSocketRequests = [];
update: It could be leftovers, but this indicates that this is code from a prerelease/debug build. simcity.SetUpDemoScreen = function () {
simcity.persistentLayout = gUIManager.LoadLayout("Layouts/PersistentPreAlpha.js", gUIManager.GetRootWindow());
simcity.SetTextOnElement(simcity.DemoExitButtonTxt, new scrui.cLocaleString("Tutorials.json", "0x0eaf7bc9", "EXIT"));
simcity.SetTextOnElement(simcity.DemoAvailableReleaseDateTxt, new scrui.cLocaleString("Tutorials.json", "0x0eaf7bb2", "AVAILABLE FEBRUARY 2013"));
simcity.SetTextOnElement(simcity.DemoThanksForPlayingTxt, new scrui.cLocaleString("Tutorials.json", "0x0eaf7b4b",
"THANKS for PLAYING"));
simcity.SetTextOnElement(simcity.DemoPreOrderTxt, new scrui.cLocaleString("Tutorials.json", "0x0eaf7bb1", "PRE-ORDER AT SIMCITY.COM"));
simcity.SetTextOnElement(simcity.DemoNotFinalSoftwareTxt, new scrui.cLocaleString("Tutorials.json", "0x0eaf7b3c", "Not Final Software"))
};That's the REST url
The Maxis team has talked quite a bit about the challenges in making their agent-based simulation engine, Glassbox, performant on low- and medium-spec PCs.
SimCity is one of those games that would benefit hugely from multi-core computers so I find the whole "We moved core functions to our servers because your computers are too puny" reasoning to be lacking.
It seems obvious that the only reason they moved processing functionality to their servers is because they have to calculate the inter-region stuff which they cannot reliably farm out to untrusted clients.
Basically they decided that the new SimCity would be a "Social" game from the outset and architected around that, the DRM side-effect is just an added "bonus" for Maxis/EA.
Of course many people (Myself included) just want a new single-player SimCity... Hell I would even take the last SimCity with corrected routing and multi-thread support.
I'm not sure to what degree exactly the new SimCity was optimized for multicore, but just a cursory glance suggests that is making use of all 4 cores in my machine. In terms of what they actually shipped to be calculated in the cloud, my guess would be macro-economic and trade conditions, as well as regional dynamics. These require a view of all the data from the region, and are thus best computed live centrally.
At the moment my team is working on a solution that allows other game dev companies to do the same thing and I'm glad to see big players taking a step in that direction.
if (something....)
return !0;
else
return !1;
is there any reason why they aren't simply using `true` and `false`?(because !1 is defined to return literally `false` and !0 to return `true`)
[1] https://gist.github.com/anonymous/5133829/raw/9340a6fdc35453...
What didn't scale was the server-side. The client-side is just fine.
As for the idea of a browser VM, it is a world we live in. Welcome to the wonders of Java applets.