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

📄 mmpdev-article.xhtml

📁 大型多人在线游戏开发,该书光盘上附带的源码
💻 XHTML
📖 第 1 页 / 共 5 页
字号:
  <li>The client is then given a remote reference object which points at the  Identity. </li>    <li>The client makes a request for some perspective using a service name /  perspective name pair, and specifying a 'client' object to connect to the  perspective once located.  This is the <code>attach</code> method in the  Identity's interface.</li>    <li>If the identity has a key for that service/perspective name pair, the  Identity looks up the appropriate service.  </li>    <li>The service then loads the perspective from its persistent storage and  returns it, calling the attached method on the loaded perspective.</li>    <li>The perspectives are returned to the client and associated with  client-side objects.  Communication from client objects begins.</li>  </ol><h3>Emergent Features</h3><p><u>Metamorphosis</u> was a very simple example of the application ofTwisted, but it nevertheless applies a number of very useful technologies.  Themost immediately obvious benefit of the example is that extremely simpleclients such as this one can be very helpful for server load-testing.  Theability to access the game server with alternate, simplified clients can beindispensable for support personnel, as both a defense against potentialinstabilities in portions of the official client code and as a mechanism forautomation of simple frequently-performed tasks.</p><p>You also benefit from the lower-level networking architecture in Twisted.After generating an encryption key, you can secure the PB connection using theindustry standard Secure Sockets Layer.  This is as simple as replacing theserver's call to <code>listenTCP</code> with <code>listenSSL</code>.</p><p>One of the other advantages of this approach is that it has good securityproperties.  Often you will want to provide certain convenience functionalityfor game-masters in the distributed client, but you don't want users to be ableto access it.  In <code>twisted.cred</code>, you can encapsulate this riskyfunctionality in a separate Perspective and never even give player Identityobjects a key to access a Perspective of that type.  This reduces the need forwriting access checks in methods; by avoiding the need for these checks, youcan't forget to put such a check in - by default, insecure functionality justwon't be available.</p><h2>Web-Based Tools</h2><p>Any discussion of integration of network technologies in this increasinglyweb-driven era has to include some mention of HTTP or legacy protocol support.Twisted includes a robust, flexible web-server, which can function both as astand-alone server and as a framework for publishing other Twisted objects onthe web. </p><p>Web browsers are ubiquitous, robust clients.  The web can serve as aconvenient mechanism for statistics reporting, an administrative front-end forsupport technicians, a place to display persistent laddering information forbragging rights, even a minimal game-client for users.</p><p>In addition to a web server, Twisted provides a templating and applicationframework for browser-based applications.  Taken together, the working titlefor these tools is WebMVC.  WebMVC takes a slightly unusual approach to theproblem of building web applications.  Many web-specific languages and serverAPIs treat a relational database as the integration point between the web andyour application, and assume that your whole application is being written forthe web alone. Twisted instead assumes that you have existing applicationcomponents that you'll want to put on web pages, and therefore hooks thoseobjects directly to the web.</p><p>To put it more simply, WebMVC treats the web more like a GUI toolkit in theModel/View/Controller pattern than a batch output format.  It is designed forreal-time, web-based interaction with a running system. </p><p>In that spirit of publishing existing objects on the web, let's take theexample from above and integrate some simple web functionality with it, bydisplaying a listing of all players.</p><p>First, we will create an HTML template which specifies our intent.</p><div class="py-listing"><pre class="htmlsource">&lt;html&gt; &lt;head&gt;&lt;title&gt;Metamorphosis Player Rankings&lt;/title&gt;&lt;/head&gt; &lt;body&gt;&lt;h1&gt;Metamorphosis Player Rankings&lt;/h1&gt;&lt;table view=&quot;bugDisplay&quot; border=&quot;1&quot;&gt;  &lt;tr&gt; &lt;th&gt;Rank&lt;/th&gt;&lt;th&gt;Name&lt;/th&gt; &lt;th&gt;Angst&lt;/th&gt; &lt;/tr&gt;  &lt;tr rowOf=&quot;bugDisplay&quot;&gt;    &lt;td columnOf=&quot;bugDisplay&quot; columnName=&quot;rank&quot; /&gt;    &lt;td columnOf=&quot;bugDisplay&quot; columnName=&quot;name&quot; /&gt;    &lt;td columnOf=&quot;bugDisplay&quot; columnName=&quot;angst&quot; /&gt;  &lt;/tr&gt;&lt;/table&gt;&lt;/body&gt; &lt;/html&gt;</pre><div class="py-caption">Rankings Web Template - <span class="py-filename">metaweb.html</span></div></div><p>WebMVC expects all template files to be well-formed XML.  If you're familiarwith HTML already, but not XML, this just means you need to put a<code>/</code> before the <code>&gt;</code> in any tag which does not close,such as HR and BR.</p><p>This file is <em>only</em> a template.  It does not specify any presentationlogic or data, only what the output ought to look like.  Notice that we arenotating certain parts of the document for use by the code, with attributessuch as <code>view</code>, <code>rowOf</code> and <code>columnOf</code>.</p><div class="py-listing"><pre class="python"><span class="py-src-keyword">from</span> twisted.web <span class="py-src-keyword">import</span> wmvc, microdom<span class="py-src-keyword">from</span> twisted.python <span class="py-src-keyword">import</span> domhelpers<span class="py-src-keyword">class</span><a name="MBuggyWorld"><span class="py-src-identifier"> MBuggyWorld</span></a>(wmvc.WModel):    <span class="py-src-keyword">def</span><a name="__init__"><span class="py-src-identifier"> __init__</span></a>(self, world, *args, **kw):        wmvc.WModel.__init__(self, world, *args, **kw)        self.world = world<span class="py-src-keyword">class</span><a name="CBuggyWorld"><span class="py-src-identifier"> CBuggyWorld</span></a>(wmvc.WController):    <span class="py-src-keyword">pass</span><span class="py-src-keyword">class</span><a name="VBuggyWorld"><span class="py-src-identifier"> VBuggyWorld</span></a>(wmvc.WView):    templateFile = <span class="py-src-string">"metaweb.html"</span>    <span class="py-src-keyword">def</span><a name="factory_bugDisplay"><span class="py-src-identifier"> factory_bugDisplay</span></a>(self, request, node):        rowNode = domhelpers.locateNodes([node], <span class="py-src-string">"rowOf"</span>, <span class="py-src-string">"bugDisplay"</span>)[0]        node.removeChild(rowNode)        bugList = self.model.world.perspectives.values()        bugList.sort(<span class="py-src-keyword">lambda</span> a, b: a.angst &lt; b.angst)        rank = 0        <span class="py-src-keyword">for</span> bug <span class="py-src-keyword">in</span> bugList:            rank += 1            rnode = rowNode.cloneNode(1)            node.appendChild(rnode)            colNodes = domhelpers.locateNodes([rnode],<span class="py-src-string">"columnOf"</span>,<span class="py-src-string">"bugDisplay"</span>)            bugDict = {<span class="py-src-string">"name"</span>: bug.perspectiveName,                       <span class="py-src-string">"angst"</span>: bug.angst,                       <span class="py-src-string">"rank"</span>: rank}            <span class="py-src-keyword">for</span> cn <span class="py-src-keyword">in</span> colNodes:                cn.appendChild(microdom.Text(str(bugDict[cn.getAttribute(<span class="py-src-string">"columnName"</span>)])))        <span class="py-src-keyword">return</span> nodewmvc.registerViewForModel(VBuggyWorld, MBuggyWorld)wmvc.registerControllerForModel(CBuggyWorld, MBuggyWorld)</pre><div class="py-caption">Presentation Logic Module - <span class="py-filename">metaweb.py</span></div></div><p>After creating a template, we create a presentation logic module, where weretrieve and format the data using the WWW Consortium (W3C) standard DocumentObject Model (DOM) API. Presentation logic in WebMVC is evaluated in roughlyfour steps.<ol>  <li>The template is read in to a DOM tree.</li>  <li>Particular nodes (those with <code>view</code> attributes) are found in a  depth-first search.</li>    <li>Methods named <code>factory_<i>[view attribute]</i></code> are invoked  with those nodes.  These methods modify the nodes in the parsed XML tree that  resulted from the template.</li>  <li>The tree, thus manipulated, is sent to the web browser as a stream of  XHTML text.</li></ol></p><p>We now need a way to test this code.  This will require going back to theearlier example, <code>fritz-franz-setup.py</code> and modifying our server toalso run an HTTP server in addition to a PB server.  Add the following snippetto that file, before the <code>app.run()</code> line.</p><div class="py-listing"><pre class="python"><span class="py-src-keyword">from</span> twisted.web.server <span class="py-src-keyword">import</span> Site<span class="py-src-keyword">from</span> twisted.web.static <span class="py-src-keyword">import</span> File<span class="py-src-keyword">from</span> twisted.web.script <span class="py-src-keyword">import</span> ResourceScriptf = File(<span class="py-src-string">'.'</span>)f.processors = { <span class="py-src-string">'.rpy'</span>: ResourceScript }app.listenTCP(8080, Site(f))</pre><div class="py-caption">Additions to make Metamorphosis a Web server. - <span class="py-filename">add-web.py</span></div></div><p>This creates a webserver that serves files out of the same directory wherethe server is running.  It also specifies a type of file which is to beinterpreted as dynamic content: any file with the extension <code>.rpy</code>is a <code>ResourceScript</code>, which means it is a Python file which isevaluated to produce an instance of a web resource.</p><p>As a final step, we must create a <code>.rpy</code> file which specifies theModel of the web application.  This  </p><div class="py-listing"><pre class="python"><span class="py-src-keyword">import</span> metaweb, __main__resource = metaweb.MBuggyWorld(__main__.buggyWorld)</pre><div class="py-caption">Resource Loader File - <span class="py-filename">metaweb.rpy</span></div></div><p>Since <code>fritz-franz-setup.py</code> is the <code>__main__</code> moduleof this program, we can locate the BuggyWorld service that we instantiatedthere.</p><p>The game is now running its own web server, which is both a full-featured,secure, file-system web server, and a dynamic window into the game world.</p><p>Of course, there's also the simple question of the corporate web-site forthe game.  Twisted Web provides direct support for the Zope application server,which is rapidly becoming an industry standard for content management.  Whilethe development of a corporate website is outside the scope of this article, Zopeintegration makes it easy to take the components described above and put theminto a website with news updates, message boards, and all the amenities of aportal site with a few clicks on a management interface. </p><h2>Integrating Independent Objects</h2><p>Object-Oriented Programming techniques have long been touted as a solutionto integration problems.  As any experienced software developer should know,there is some truth to this claim, but it has been endlessly exaggerated bysoftware development tool companies.  The hit-and-miss nature of OOP can mostlybe traced to 2 factors: an overly broad definition of what is and is not<q>Object Oriented</q>, and an institutional unwillingness to separate thetechniques used in OOP into <q>good</q> and <q>bad</q> categories.</p><p>So far, we have discussed how to make use of Twisted's services tofacilitate integrating with external tools.  Now we will touch on how it is

⌨️ 快捷键说明

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