⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmpdev-article.xhtml

📁 大型多人在线游戏开发,该书光盘上附带的源码
💻 XHTML
📖 第 1 页 / 共 5 页
字号:
<?xml version="1.0"?><html lang="en" xmlns="http://www.w3.org/1999/xhtml">  <head><title>Massively Multiplayer Game Development Article: MMP Gems Article: Using the Twisted Framework for MMP ServiceIntegration</title><link href="stylesheet.css" type="text/css" rel="stylesheet"/>  </head>  <body bgcolor="white">    <div class="content"><h1>Using the Twisted Framework for MMP Service Integration</h1><h2>A Brief Description of the Problem</h2><p>Massively multiplayer games are among the most complex software systems inthe world.  Allowing thousands of people to run around in the same space at thesame time, fighting the same enemies and exhausting the same resources, is apretty major challenge.  There is another important challenge that these gamesmust face, though, which is often ignored and deferred to ad-hoc implementationlater by a Live Team.  Integrating external services into an MMP virtual worldis difficult, and will increase in importance as MMP games make their wayfurther towards the mainstream gaming audience and the stakes for keepingsubscribers get higher.</p><p>There are some obvious bits of functionality that a game will need thatexternal tools can help with.  Games need a chat system; if for nothing else,to interact with your customers and provide support inside the game.Third-party messaging systems can implement that.  External reporting tools canextract game data from a relational database and provide reports to marketingpersonnel and executives.</p><p>Once the game's core functionality is already designed, it may be temptingto ignore integrating extra stuff.  Why bother integrating an external chatsystem when you've got a perfectly clear design for one?  The organizationaleffort, both political and technical, of providing mechanisms for third-partyintegration is substantial, and it's a common decision to forego it forschedule-related reasons.</p><p>Looking at only these initial problems, the call is difficult to make.Integration provides some benefits, but may not be worth the effort.  Once youstart looking out towards the horizon of a game's lifetime, though, it becomesclear that integration is unavoidable: the best you can do is prepare forit. </p><p>For example, let's say that as it inevitably happens, there is a bug in someversion of the client software that a group of player figures out how toexploit to crash other people out of the game.  If there is only one mechanismfor accessing the game world -- the release game client (perhaps withgame-master extensions for trusted users) -- then there is no recourse forsupport personnel to access the game world and correct potential problemscaused by this flaw until it is corrected by developers; this may take days oreven weeks, depending on the severity or complexity of the problem.</p><p>The complexity of simple additions, such as chat, is often underestimated.For example, players who find the in-game chat system too restrictive orlimiting will resort to using other, external programs that better suit theirneeds.  Your support staff may find themselves responding to reports of playersbeing harassed by other players on chat services like internet relay chat, onservers that they cannot even log in to, let alone get log files andadministrator access.</p><p>The benefits of integrating with a relational database for data storagerather than doing one's own ad-hoc data storage mechanism are more widelyunderstood: writing your own data storage layer means you need to write all ofyour own reporting and extraction tools as well, not to mention the difficultyof getting storage management done right in the first place!</p><p>This may all seem like a long-winded appeal to the well-worn object-oriented<q>software reuse</q> rhetoric.  It's not the same, though; integrating withexisting, working, proven solutions is better than writing your own, in caseswhere the problem is not your business's core area of competency.  Even if yourorganization is capable of making fantastic re-use of code developedinternally, it's not as good as never having to do that development at all.</p><p>In other words, do you <em>really</em> want to be developing yet anothertechnical support ticket-tracking system this year, or do you want to bewriting a game that's compelling and fun? </p><h2>The Problems with Doing It Yourself</h2><p>Questions of integration and extensibility work their way into every layerof a system.  Making a robust, extensible infrastructure is a very challengingproblem.  It's also a totally different problem than making a simple, playable,shippable game.  In fact, as the Extreme Programming methodology indicates, itis a waste of resources to prematurely plan for extensibility; the only way toreally determine if a particular mechanism for extension is necessary is tofind a use-case for it.</p><p>This doesn't mean that you'll never need extensibility.  It means that theonly way to build an extensible system is to have it hammered on over a longperiod of time by a large base of users with diverse interests, to expose whereit really needs to be extended, improved, and stabilized. </p><p>Purpose-built frameworks do not integrate different services well, preciselybecause their audience is limited and their time of development is often short.It is difficult to anticipate the hooks you will need later in development toprovide unexpected functionality, and guessing wrong will take time away fromimportant core features to implement potentially useless extensions.  Buildingan infrastructure that works great for your gameplay may end up being a seriousliability for your customer support.</p><p>Finally, if you build an infrastructure yourself from top to bottom, even ifit is brilliant and wonderful and extensible, what third-party developers willbe able to add features, either for free or in commercial bundles, that youwould find useful?  Even the best-designed modular integration package isn'tuseful if knowledge about how to build modules for it is limited to a smallgroup. </p><h2>The Problems with Paying Somebody to Do It For You</h2><p>Existing <q>turnkey</q> MMP solutions have surprisingly similar problems.While they provide a lot more tools <q>out of the box</q>, their extremely highcost keeps third-party developers from creating any additional tools.  At best,you will be in a situation where you can price different components ofinfrastructure from the same vendor separately, and that model is stillunusual.  Restrictive licensing agreements make development of open-sourcecomponents for these systems difficult if not impossible.  As more and moregames turn to BSD and Linux servers, using open-source components internallylike Python and Lua, the importance of these robust back-end tools isincreasingly obvious.</p><p>Packaged MMP solutions are also sometimes flexible in the wrong areas.  Theywill provide a complete implementation of game-world infrastructure, limitingthe possibilities for unusual gameplay, but they will not provide externaltools that are not interesting for game developers to experiment with.</p><p>Outside of the game industry, other kinds of general networking, distributedcomputing, and data-storage infrastructure exist.  This category comprisesthings like implementations of the J2EE API. From their product descriptions,these might sound appropriate starting-points for game infrastructure.</p><p>Unfortunately, most of these products are highly expensive middlewaretargeted at batch transaction processing.  Games involve a dynamic, event-basedinteractions.  Infrastructure that cannot respond to player actions in softreal-time can't be made to work for the most basic operations in the gameworld, regardless of suitability for any other integration tasks.</p><h2>A Summary of the Problem</h2><p>In order to allow for the flexibility necessary to economically run amassively multiplayer game, it's important to use an infrastructure fordevelopment which allows for the event-based nature of multiplayer games,provides enough services to make any additional training expenses worthwhile,and provides public programming interfaces so that more than one group'sexpertise can be brought to bear on the very different problem domains thatmake a complete MMP solution. </p><h2>Framing a Solution</h2><p>The Twisted Network Framework is one such solution.  Although it is acompletely generic network applications platform, already in use in severaldifferent application domains, it was designed from the beginning with supportfor massively multiplayer games as a design goal.  As Open Source software,there is a large and enthusiastic community.  It is also an event-basednetworking platform with support both for high-level programming (in Python)and speed-critical extensions (in C and C++). </p><p>Twisted may not be appropriate for everyone.  If for some reason thespecific implementations described in this article are inappropriate for yourspecific needs, keep in mind that the problems remain, and similar approachesto the solution are probably a good idea.</p><p>In providing code examples, I will assume a familiarity both with the basicsof network programming and Python.  I'll be discussing these tools in thecontext of a hypothetical game called <q>Metamorphosis Online</q>, in which theplayers are clinically depressed insects. </p><h2>A Gentle Introduction: Generalized Deferred Execution</h2><p>One of the most basic ways in which Twisted allows network applications tobe integrated is that it specifies a general mechanism for wrapping potentiallyblocking activities.</p><p>In many asynchronous networking frameworks, the primary way that blockingactivities are represented are as callbacks.  Objects conforming to a specificinterface must be passed in as an argument to any function which needs to waitfor a blocking operation. These interfaces often differ for different types ofblocking operations, which creates two problems.  One, passing additionalarguments to the callbacks may be unwieldy.  Two, since the interfaces aredifferent, any two blocking systems that want to communicate must have specificglue code between them, and often present a third, different publicinterface. </p><p>Twisted eliminates these problems with the<code>twisted.internet.defer</code> module.  <em>All</em> functions which maywait on a blocking operation will result return <code>Deferred</code>instances.  A <code>Deferred</code> acts as two logical chains of functions;one for errors and one for results.  When the result of a Deferred becomesavailable, it passes it to the first callback in the chain, then passes theresult of that callback to the second.  If there is ever an error, theerror-handling callback is invoked instead. This was inspired in part by the"Eventually" operator in the E language and has most of its deadlock-avoidanceproperties.</p><p>Also, because <code>Deferred</code> will accept any function which takes oneargument and returns one result, many python standard library functions willwork fine. </p><p>Here are some examples of how Deferred is used.</p><div class="py-listing"><pre class="python"><span class="py-src-keyword">def</span> printResult(x):    <span class="py-src-keyword">print</span> <span class="py-src-string">'result:'</span>,x<span class="py-src-comment"># remote method call</span>remoteObject.callRemote(<span class="py-src-string">"test"</span>).addCallback(printResult)<span class="py-src-comment"># database interaction</span>dbInterface.runQuery(<span class="py-src-string">"select * from random_table"</span>).addCallback(printResult)<span class="py-src-comment"># threadpool execution</span><span class="py-src-keyword">def</span><a name="myMethod"><span class="py-src-identifier"> myMethod</span></a>(a, b, c):    <span class="py-src-keyword">return</span> a + b + cdeferToThread(myMethod, 1, 2, 3).addCallback(printResult)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -