Faunis/0000775000175000017500000000000012062730612011022 5ustar useruserFaunis/fdl-1.3.txt0000644000175000017500000005466212062715036012645 0ustar useruser GNU Free Documentation License Version 1.3, 3 November 2008 Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. The "publisher" means any person or entity that distributes copies of the Document to the public. A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements". 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License. However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Document. 11. RELICENSING "Massive Multiauthor Collaboration Site" (or "MMC Site") means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A "Massive Multiauthor Collaboration" (or "MMC") contained in the site means any set of copyrightable works thus published on the MMC site. "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization. "Incorporate" means to publish or republish a Document, in whole or in part, as part of another Document. An MMC is "eligible for relicensing" if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008. The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing. ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright (c) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts." line with this: with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software. Faunis/.project0000644000175000017500000000055512061412430012466 0ustar useruser Faunis org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature Faunis/serverData/0000775000175000017500000000000012062730610013120 5ustar useruserFaunis/serverData/accounts/0000775000175000017500000000000012062730610014737 5ustar useruserFaunis/serverData/accounts/user2/0000775000175000017500000000000012062730610015777 5ustar useruserFaunis/serverData/accounts/user2/account.txt0000644000175000017500000000000512055474662020203 0ustar useruseruser2Faunis/serverData/accounts/user2/players/0000775000175000017500000000000012062730610017456 5ustar useruserFaunis/serverData/accounts/user2/players/oso2/0000775000175000017500000000000012062730610020340 5ustar useruserFaunis/serverData/accounts/user2/players/oso2/oso20000644000175000017500000000070012061733654021152 0ustar userusersr server.Player IxIyL accountNametLjava/lang/String;L currentEmoteq~LcurrentMapNameq~L directiontLcommunication/enums/Direction;Lnameq~LpathtLcommunication/movement/Path;Ltypet$Lcommunication/enums/CharacterClass;xp tuser2pt greenFields~rcommunication.enums.Directionxrjava.lang.Enumxptrighttoso2p~r"communication.enums.CharacterClassxq~ tarctosFaunis/serverData/accounts/user1/0000775000175000017500000000000012062730610015776 5ustar useruserFaunis/serverData/accounts/user1/account.txt0000644000175000017500000000000712055474640020200 0ustar useruseruser1 Faunis/serverData/accounts/user1/players/0000775000175000017500000000000012062730610017455 5ustar useruserFaunis/serverData/accounts/user1/players/oso1/0000775000175000017500000000000012062730610020336 5ustar useruserFaunis/serverData/accounts/user1/players/oso1/oso10000644000175000017500000000067712062726176021166 0ustar userusersr server.Player IxIyL accountNametLjava/lang/String;L currentEmoteq~LcurrentMapNameq~L directiontLcommunication/enums/Direction;Lnameq~LpathtLcommunication/movement/Path;Ltypet$Lcommunication/enums/CharacterClass;xptuser1pt greenFields~rcommunication.enums.Directionxrjava.lang.Enumxptdowntoso1p~r"communication.enums.CharacterClassxq~ tarctosFaunis/.settings/0000775000175000017500000000000012062730610012736 5ustar useruserFaunis/.settings/org.eclipse.jdt.core.prefs0000644000175000017500000000116611546033632017730 0ustar useruser#Sun Apr 03 11:02:17 CEST 2011 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.6 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.source=1.6 Faunis/Makefile0000644000175000017500000000176212062717630012473 0ustar useruser# Copyright 2012 Simon Ley alias "skarute" # # This file is part of Faunis. # # Faunis is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of # the License, or (at your option) any later version. # # Faunis is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General # Public License along with Faunis. If not, see # . JAVAC = javac -sourcepath ./src/ -classpath ./bin/ -d ./bin/ JAVA = java -enableassertions -classpath ./bin/ compile: $(JAVAC) ./src/client/Client.java $(JAVAC) ./src/server/MainServer.java runClient: $(JAVA) client/Client runServer: $(JAVA) server/MainServer clean: rm -rf ./bin/* Faunis/devdoc.txt0000644000175000017500000001447112062725306013040 0ustar useruserCopyright 2012 Simon Ley alias "skarute" This documentation is published under the GNU Free Documentation License v1.3 or later. You can find a copy of this license in "fdl-1.3.txt" or at . ######################################## Faunis Developers' Documentation ######################################## This documentation is still incomplete. I'm working on it. :o( 1. Concurrency Lots of synchronised statements are used to avoid problems with concurrency. To avoid deadlocks, all class fields are reserved from top to bottom as their definitions appear in the class. After them, all variables not part of the class are reserved. 2. Code structure In general, the classes are structured in three main packages: "client" contains everything only needed by the client, "server" everything only needed by the server, and communication contains everything which is needed by both or which is exchanged during client-server communication. All exchanged communication messages are called orders and carry a prefix of two letters to better distinguish between them. The first letter indicates where the order is from (there are some few exceptions where this isn't true, though), while the second letter indicates who the recipient is. C stands for Client, B for Butler, M for MapManager. Playable characters are represented by the Player class on the server side and by the PlayerGraphics class on the client side. Certain player data relevant for both sides is in GraphicalPlayerStatus which primarily stores information about how the character is displayed. Note that the PlayerGraphics instance can completely be produced from the GraphicalPlayerStatus object. 2.1 Client side There is the Client class which represents the main client functionality and has the main method. The user interface is represented by the class GraphWin (basic gaming interface) and GameWindow (specialised for client functionality). 2.1.1 Animation The more complicated part on the client side is the animation stuff: A character frame can be drawn as a whole (compact AniCompoType) or consist of separate limb images (limbed AniCompoType). The compact style is easier to create (since even if you decide to isolate the frame into single limbs, you will have to draw it as a whole anyway just to see if the limbs are proportional), but the limbed style has the advantage that later the character can keep its facial expression during emotes, amongst others. All frames that form one animation cycle are stored in a Bone instance, which therefore is determined by character class, animation / emote state, body part and direction. An animation can have different termination behaviour: It can simply return to the default standing animation (revert AniEndType), it can be repeated endlessly (repeat AniEndType), or it can stay in the last frame (end AniEndType). Except for standing and walking, every animation can be triggered as an emote for now. Note that a walk command will remove any emote in progress. The GraphicsContentManager is responsible for loading and storing these Bones and will provide them if requested. He also keeps information about AniCompoType and AniEndType. The reason why he is also used on the server side is because the server has to verify if an emote is valid, and must know its AniEndType to handle it correctly. The methods for loading the image files are actually not called on the server side. 2.1.2 Animators and Movers Whenever a player is moving, a Mover is instantiated on both client and server side (stored in Client resp. MapManager). His task is to regularly adjust the player's position, thus he has an own Timer that frequently executes a TimerTask, in our case an instance of RoughMovingTask on the server side or SoftMovingTask on the client side. Reason for this differentiation is that on the server side it's enough to simply change the coordinates by one step during every task execution, but on the client side that would look too rough and we want a smooth transition between fields. That's why the SoftMovingTask also adjusts a special attribute, the so-called deltaLevel (I couldn't come up with a better name, I'm sorry). It indicates the relative position shift with relation to the recorded coordinates. The deltaLevel is only one value though for a two-dimensional shift we'd need two, however we still have the player's direction, so it is sufficient. Like with movement, there's a similar approach with animation: The Animator class similarly has its own timer and timerTask to increment a player's frame counter and to handle animation termination. All Animators are kept by the Client class. Since there is no need to have frame counters on the server side, there are no Animators there. 2.2 Server side The server side main class is MainServer, where at last all data references are hold. There is a Reception class which steadily looks out for new connecting clients and redirects them to a newly created Butler. The Butler class represents a client on the server side. Besides the reception, he is the only one directly communicating with him, checking and implementing his orders as well as returning the orders meant for him. When the client disconnects, the butler is destroyed. For each map of the game, there exists a MapManager who manages the list of players / butlers that are currently on this map. Every player / butler who holds an active player must be registered at a mapman. Whenever something happens on the map that others should perceive, the mapman sends orders to all butlers to notify them about the change. 3. Threads Client: - main thread: frequently redraws the screen - one thread to handle user input - one to respond to server orders MainServer: - main thread: Only used for initialisation and to make the window visible Butler: - one to handle orders from the client side - one to handle orders from the server side (mapman etc.) MapManager: - one to handle the butlers' orders Reception: - one to receive incoming clients Furthermore every Animator and Mover has its own thread. 4. What isn't implemented so far - maps in general - everything that turns a MMOG into a MMORPG: Fighting and attributes - inventory and items - security and encryption (minimum requirements for a stable version!), data backup - better administration - and much, much more... Faunis/src/0000775000175000017500000000000012062730610011607 5ustar useruserFaunis/src/communication/0000775000175000017500000000000012062730610014454 5ustar useruserFaunis/src/communication/MapInfo.java0000644000175000017500000000222312060472556016657 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication; import java.io.Serializable; import java.util.HashMap; public class MapInfo implements Serializable { private static final long serialVersionUID = 1L; public String mapName; public HashMap players; public MapInfo(String mapName, HashMap players) { this.mapName = mapName; this.players = players; } } Faunis/src/communication/GraphicalPlayerStatus.java0000644000175000017500000000300412061420306021562 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication; import java.io.Serializable; import communication.enums.CharacterClass; import communication.enums.Direction; import communication.movement.Path; /** Contains the whole information about how to correctly draw a player in its current * state. Is transmitted in serialised form. */ public class GraphicalPlayerStatus implements Serializable { private static final long serialVersionUID = 1L; public String name; public CharacterClass type; public int x; public int y; public Direction direction; public Path path = null; public String currentEmote; // "revert" emotes may also be stored here public boolean hasPath() { return (path != null); } public boolean hasEmote() { return (currentEmote != null); } } Faunis/src/communication/OwnPlayerExtendedInfo.java0000644000175000017500000000147312060472556021551 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication; public class OwnPlayerExtendedInfo { } Faunis/src/communication/butlerToClientOrders/0000775000175000017500000000000012062730610020572 5ustar useruserFaunis/src/communication/butlerToClientOrders/BCRemoveCharOrder.java0000644000175000017500000000241712061575046024704 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.butlerToClientOrders; import server.mapmanToButlerOrders.MBRemoveCharOrder; /** The butler tells the client that the character defined by this order * has left the map and should no longer be displayed. */ public class BCRemoveCharOrder extends BCOrder { private static final long serialVersionUID = 1L; private String playerName; public BCRemoveCharOrder(MBRemoveCharOrder order) { this.playerName = order.getPlayerName(); } public String getPlayerName() { return playerName; } } Faunis/src/communication/butlerToClientOrders/BCSetMapOrder.java0000644000175000017500000000272512061575306024043 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.butlerToClientOrders; import server.mapmanToButlerOrders.MBMapInfoOrder; import communication.MapInfo; /** The butler tells the client that the map defined by this order * should be shown, including info about all characters on the new map. */ public class BCSetMapOrder extends BCOrder { private static final long serialVersionUID = 1L; private MapInfo mapInfo; private String activePlayerName; public BCSetMapOrder(MBMapInfoOrder order, String activePlayerName) { this.mapInfo = order.getMapInfo(); this.activePlayerName = activePlayerName; } public MapInfo getMapInfo() { return mapInfo; } public String getActivePlayerName() { return activePlayerName; } } Faunis/src/communication/butlerToClientOrders/BCSetClientStatusOrder.java0000644000175000017500000000226012061575212025736 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.butlerToClientOrders; import communication.enums.ClientStatus; /** The butler tells the client that his client status should change. */ public class BCSetClientStatusOrder extends BCOrder { private static final long serialVersionUID = 1L; private ClientStatus newStatus; public BCSetClientStatusOrder(ClientStatus newStatus) { this.newStatus = newStatus; } public ClientStatus getNewStatus() { return this.newStatus; } } Faunis/src/communication/butlerToClientOrders/BCChatMessageOrder.java0000644000175000017500000000255112061575146025035 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.butlerToClientOrders; /** The butler tells the client that a system message should be shown. */ public class BCChatMessageOrder extends BCOrder { private static final long serialVersionUID = 1L; private String message; private String fromName; private boolean isBroadcast; public BCChatMessageOrder(String message, String fromName, boolean isBroadcast) { this.message = message; this.fromName = fromName; this.isBroadcast = isBroadcast; } public String getMessage() { return message; } public String getFromName() { return fromName; } public boolean isBroadcast() { return isBroadcast; } } Faunis/src/communication/butlerToClientOrders/BCAddCharOrder.java0000644000175000017500000000272312061574662024142 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.butlerToClientOrders; import communication.GraphicalPlayerStatus; import server.mapmanToButlerOrders.MBAddCharOrder; /** The butler tells the client that the character defined by this order * has joined the map and should be displayed. */ public class BCAddCharOrder extends BCOrder { private static final long serialVersionUID = 1L; private String playerName; private GraphicalPlayerStatus graphStatus; public BCAddCharOrder(MBAddCharOrder order) { this.playerName = order.getPlayerName(); this.graphStatus = order.getGraphStatus(); } public String getPlayerName() { return playerName; } public GraphicalPlayerStatus getGraphStatus() { return graphStatus; } } Faunis/src/communication/butlerToClientOrders/BCOrder.java0000644000175000017500000000166612061573664022741 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.butlerToClientOrders; import java.io.Serializable; public abstract class BCOrder implements Serializable { private static final long serialVersionUID = 1L; } Faunis/src/communication/butlerToClientOrders/BCErrorMessageOrder.java0000644000175000017500000000214212061575122025235 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.butlerToClientOrders; /** The butler tells the client that an error message should be shown. */ public class BCErrorMessageOrder extends BCOrder { private static final long serialVersionUID = 1L; private String message; public BCErrorMessageOrder(String message) { this.message = message; } public String getMessage() { return this.message; } } Faunis/src/communication/butlerToClientOrders/BCChangeCharOrder.java0000644000175000017500000000303312061575026024625 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.butlerToClientOrders; import server.mapmanToButlerOrders.MBChangeCharOrder; import communication.GraphicalPlayerStatus; /** The butler tells the client that the character defined by this order * has changed the graphical status, so that the client can adjust the * way the character is displayed. */ public class BCChangeCharOrder extends BCOrder { private static final long serialVersionUID = 1L; private String playerName; private GraphicalPlayerStatus graphStatus; public BCChangeCharOrder(MBChangeCharOrder order) { this.playerName = order.getPlayerName(); this.graphStatus = order.getGraphStatus(); } public String getPlayerName() { return playerName; } public GraphicalPlayerStatus getGraphStatus() { return graphStatus; } } Faunis/src/communication/butlerToClientOrders/BCSystemMessageOrder.java0000644000175000017500000000214412061576066025442 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.butlerToClientOrders; /** The butler tells the client that a system message should be shown. */ public class BCSystemMessageOrder extends BCOrder { private static final long serialVersionUID = 1L; private String message; public BCSystemMessageOrder(String message) { this.message = message; } public String getMessage() { return this.message; } } Faunis/src/communication/MapContentManager.java0000644000175000017500000000225212060472556020673 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication; import java.util.HashMap; public class MapContentManager { private static MapContentManager instance; private HashMap mapnameToMap; public static void initialize() { // TODO } public static MapContentManager getInstance() { return instance; } public Map getByName(String mapName) { synchronized(mapnameToMap) { return mapnameToMap.get(mapName); } } } Faunis/src/communication/GraphicsContentManager.java0000644000175000017500000002764512061716332021725 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Set; import client.Bone; import client.Client; import client.AnimationData; import communication.enums.AniCompoType; import communication.enums.AniEndType; import communication.enums.BodyPart; import communication.enums.CharacterClass; import communication.enums.Direction; public class GraphicsContentManager { private String graphicsPath; private String fileEnding; private HashMap>>> bones; private HashMap> drawingOrders; private List compactDrawingOrder; private HashMap> availableAnimationsAndData; private HashMap> availableFaces; private HashMap compositionTypes; /** Don't forget to call loadResourcesForClient() / loadResourcesForServer() * afterwards! */ public GraphicsContentManager(String graphicsPath, String fileEnding) { this.graphicsPath = graphicsPath; this.fileEnding = fileEnding; } /** Must be called by client after calling the content manager's constructor, * will initialise all the fields that the client needs. */ public void loadResourcesForClient() { compactDrawingOrder = new ArrayList(); compactDrawingOrder.add(BodyPart.compact); bones = new HashMap>>>(); drawingOrders = new HashMap>(); loadDrawingOrders(); compositionTypes = new HashMap(); loadCompositionTypes(); availableAnimationsAndData = new HashMap>(); loadAvailableAnimations(true); availableFaces = new HashMap>(); loadAvailableFaces(); loadImages(); } /** Must be called by server after calling the content manager's constructor, * will initialise all the fields that the server needs. */ public void loadResourcesForServer() { availableAnimationsAndData = new HashMap>(); loadAvailableAnimations(false); availableFaces = new HashMap>(); loadAvailableFaces(); } public HashMap> getDrawingOrders() { return this.drawingOrders; } public List getDrawingOrder(Direction direction) { return this.drawingOrders.get(direction); } public List getCompactDrawingOrder() { return compactDrawingOrder; } public Set getAvailableAnimations(CharacterClass type) { return availableAnimationsAndData.get(type).keySet(); } public AnimationData getAnimationData(CharacterClass type, String animation) { return availableAnimationsAndData.get(type).get(animation); } public List getAvailableFaces(CharacterClass type) { return availableFaces.get(type); } public AniCompoType getCompositionType(CharacterClass type) { return compositionTypes.get(type); } /** Determines which animations are available for which character class. * If given flag countFrames is set, stores the number of frames available for * an animation (Takes body/down as reference, though all limbs/directions must have * the same number).
* Note that if frames should be counted, this method will require compositionTypes * to be initialised. */ private void loadAvailableAnimations(boolean countFrames) { for (CharacterClass type : CharacterClass.values()) { File typeDirectory = new File(graphicsPath+type.toString()); File[] subdirs = typeDirectory.listFiles(Client.directoryFilter); HashMap animationAndData = new HashMap(); if (subdirs != null) { for (File subdir : subdirs) { String animation = subdir.getName(); if (!animation.equals("faces")) { int numFrames = 0; if (countFrames) { String prefix; if (compositionTypes.get(type) == AniCompoType.limbed) prefix = graphicsPath+type+"/" +animation+"/body/down"; else prefix = graphicsPath+type+"/" +animation+"/down"; numFrames = countAvailableFrames(prefix); System.out.println("Animation "+animation+" of "+type+" has "+numFrames+" frames."); } AniEndType endType = determineEndType(type, animation); AnimationData animationData = new AnimationData(numFrames, endType); animationAndData.put(animation, animationData); } } } availableAnimationsAndData.put(type, animationAndData); } } private void loadAvailableFaces() { for (CharacterClass type : CharacterClass.values()) { File faceDirectory = new File(graphicsPath+type.toString()+"/faces"); File[] subdirs = faceDirectory.listFiles(Client.directoryFilter); if (subdirs == null) continue; List faceList = new ArrayList(); for (File subdir : subdirs) { String subdirName = subdir.getName(); faceList.add(subdirName); } availableFaces.put(type, faceList); } } private void loadCompositionTypes() { for (CharacterClass type : CharacterClass.values()) { File bodyDirectory = new File(graphicsPath+type.toString()+"/stand/body"); if (bodyDirectory.isDirectory() && bodyDirectory.exists()) { System.out.println(type+" has limbed graphics."); compositionTypes.put(type, AniCompoType.limbed); } else { System.out.println(type+" has compact graphics."); compositionTypes.put(type, AniCompoType.compact); } } } /** determines in which order body parts have to be drawn */ private void loadDrawingOrders() { List leftList = Arrays.asList( new BodyPart[] {BodyPart.rightArm, BodyPart.rightLeg, BodyPart.body, BodyPart.head, BodyPart.leftLeg, BodyPart.leftArm} ); drawingOrders.put(Direction.left, leftList); List rightList = Arrays.asList( new BodyPart[] {BodyPart.leftArm, BodyPart.leftLeg, BodyPart.body, BodyPart.head, BodyPart.rightLeg, BodyPart.rightArm} ); drawingOrders.put(Direction.right, rightList); List downList = Arrays.asList( new BodyPart[] {BodyPart.body, BodyPart.leftLeg, BodyPart.rightLeg, BodyPart.leftArm, BodyPart.rightArm, BodyPart.head} ); drawingOrders.put(Direction.down, downList); List upList = Arrays.asList( new BodyPart[] {BodyPart.body, BodyPart.leftLeg, BodyPart.rightLeg, BodyPart.leftArm, BodyPart.rightArm, BodyPart.head} ); drawingOrders.put(Direction.up, upList); } private void loadImages() { for (CharacterClass type : CharacterClass.values()) { AniCompoType compoType = compositionTypes.get(type); for (String animation : getAvailableAnimations(type)) { AnimationData animationData = getAnimationData(type, animation); int countFrames = animationData.numberOfFrames; String prefixString = graphicsPath+type+"/"+animation+"/"; for (BodyPart part : BodyPart.values()) { if (compoType == AniCompoType.compact && part != BodyPart.compact) continue; if (compoType != AniCompoType.compact && part == BodyPart.compact) continue; for (Direction dir:Direction.values()) { String prefixString2; if (part != BodyPart.compact) prefixString2 = prefixString+part+"/"+dir; else prefixString2 = prefixString+dir; if (countFrames == 0) { // load non-animation String address = prefixString2+fileEnding; if (!new File(address).exists()) { System.out.println("couldn't load "+address); continue; } System.out.println("load "+address); Bone bone = new Bone(address); addBone(type, animation, part, dir, bone); } else if (countFrames > 0) { // load animation with multiple frames String toCheck = prefixString2+"0"+fileEnding; if (!new File(toCheck).exists()) { System.out.println("couldn't load "+toCheck); continue; } System.out.println("load "+prefixString2+"*"+fileEnding); Bone bone = new Bone(prefixString2, fileEnding, countFrames-1); addBone(type, animation, part, dir, bone); } else { System.out.println("WARNING: Animation "+animation+" of "+type+" hasn't any pictures!"); } } } } } } /** Detects if there are multiple numbered picture files (returns their number) * or only a single un-numbered file (returns 0). If neither is found, * returns -1. */ private int countAvailableFrames(String prefixString) { File noAnim = new File(prefixString+fileEnding); if (noAnim.exists()) return 0; int counter = 0; while (new File(prefixString+counter+fileEnding).exists()) { counter++; } if (counter == 0) { System.out.println("WARNING: Couldn't find neither single picture nor animation frames!"); return -1; } return counter; } private AniEndType determineEndType(CharacterClass type, String animation) { File settingsFile = new File(graphicsPath+type+"/"+animation +"/aniSettings.txt"); assert(settingsFile.exists()); BufferedReader reader; String endTypeString; try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(settingsFile))); endTypeString = reader.readLine(); reader.close(); } catch(IOException e) { System.out.println("Couldn't read settings for animation "+animation+" of "+type+"!"); return null; } System.out.println("Animation "+animation+" of "+type+" should be of AniEndType \""+endTypeString+"\"."); return AniEndType.valueOf(endTypeString); } private void addBone(CharacterClass type, String animation, BodyPart part, Direction dir, Bone bone) { HashMap>> map = bones.get(type); if (map == null) { map = new HashMap>>(); bones.put(type, map); } HashMap> map2 = map.get(animation); if (map2 == null) { map2 = new HashMap>(); map.put(animation, map2); } HashMap map3 = map2.get(part); if (map3 == null) { map3 = new HashMap(); map2.put(part, map3); } assert(!map3.containsKey(dir)); map3.put(dir, bone); } public Bone getBone(CharacterClass type, String animation, BodyPart part, Direction dir) { HashMap>> map = bones.get(type); if (map == null) return null; HashMap> map2 = map.get(animation); if (map2 == null) return null; HashMap map3 = map2.get(part); if (map3 == null) return null; return map3.get(dir); } } Faunis/src/communication/clientToButlerOrders/0000775000175000017500000000000012062730610020572 5ustar useruserFaunis/src/communication/clientToButlerOrders/CBSetFaceOrder.java0000644000175000017500000000176712061576442024173 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.clientToButlerOrders; /** The client tells the butler that he wants to make the active player show * a certain facial expression. */ public class CBSetFaceOrder extends CBOrder { private static final long serialVersionUID = -2353951011956540653L; } Faunis/src/communication/clientToButlerOrders/CBCreatePlayerOrder.java0000644000175000017500000000225612061576204025227 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.clientToButlerOrders; /** The client tells the butler that a new character should be created under * the logged account. */ public class CBCreatePlayerOrder extends CBOrder { private static final long serialVersionUID = 1L; private String playerName; public CBCreatePlayerOrder(String playerName) { this.playerName = playerName; } public String getPlayerName() { return playerName; } } Faunis/src/communication/clientToButlerOrders/CBLoadPlayerOrder.java0000644000175000017500000000225612061576264024711 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.clientToButlerOrders; /** The client tells the butler that he wants to load an existing character * from the logged account. */ public class CBLoadPlayerOrder extends CBOrder { private static final long serialVersionUID = 1L; private String playerName; public CBLoadPlayerOrder(String playerName) { this.playerName = playerName; } public String getPlayerName() { return playerName; } } Faunis/src/communication/clientToButlerOrders/CBChatOrder.java0000644000175000017500000000246412061576150023527 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.clientToButlerOrders; /** The client tells the butler that he wants to send a chat message. */ public class CBChatOrder extends CBOrder { private static final long serialVersionUID = 1L; private String message; private String toName; /** If toName = "" or null, then the message will be broadcast on the map. */ public CBChatOrder(String message, String toName){ this.message = message; this.toName = toName; } public String getMessage() { return message; } public String getToName() { return toName; } } Faunis/src/communication/clientToButlerOrders/CBDisconnectOrder.java0000644000175000017500000000171712061576220024737 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.clientToButlerOrders; /** The client tells the butler that he wants to disconnect. */ public class CBDisconnectOrder extends CBOrder { private static final long serialVersionUID = 1L; } Faunis/src/communication/clientToButlerOrders/CBOrder.java0000644000175000017500000000176412061573556022740 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.clientToButlerOrders; import java.io.Serializable; /** Represents a request from the client to the server side */ public abstract class CBOrder implements Serializable { private static final long serialVersionUID = 1L; } Faunis/src/communication/clientToButlerOrders/CBLogoutOrder.java0000644000175000017500000000170712061576314024122 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.clientToButlerOrders; /** The client tells the butler that he wants to log out. */ public class CBLogoutOrder extends CBOrder { private static final long serialVersionUID = 1L; } Faunis/src/communication/clientToButlerOrders/CBTriggerEmoteOrder.java0000644000175000017500000000217712061576506025253 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.clientToButlerOrders; /** The client tells the butler that he wants to make the active player show * a certain gesture. */ public class CBTriggerEmoteOrder extends CBOrder { private static final long serialVersionUID = 2134927626424448916L; private String emote; public CBTriggerEmoteOrder(String emote) { this.emote = emote; } public String getEmote() { return emote; } } Faunis/src/communication/clientToButlerOrders/CBUnloadPlayerOrder.java0000644000175000017500000000173612061576524025255 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.clientToButlerOrders; /** The client tells the butler that he wants to unload the active player. */ public class CBUnloadPlayerOrder extends CBOrder { private static final long serialVersionUID = 1L; } Faunis/src/communication/clientToButlerOrders/CBMoveOrder.java0000644000175000017500000000233412061576336023560 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.clientToButlerOrders; /** The client tells the butler that he wants to move the active player. */ public class CBMoveOrder extends CBOrder { private static final long serialVersionUID = 1L; private int xTarget; private int yTarget; public CBMoveOrder(int xTarget, int yTarget) { this.xTarget = xTarget; this.yTarget = yTarget; } public int getXTarget() { return xTarget; } public int getYTarget() { return yTarget; } } Faunis/src/communication/clientToButlerOrders/CBServerSourceOrder.java0000644000175000017500000000172412061576360025300 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.clientToButlerOrders; /** A request about how to get the server's * source code, as demanded by the GNU AGPL. */ public class CBServerSourceOrder extends CBOrder { private static final long serialVersionUID = 1L; } Faunis/src/communication/clientToButlerOrders/CBLoginOrder.java0000644000175000017500000000235512061576304023720 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.clientToButlerOrders; /** The client tells the butler that he wants to log in. */ public class CBLoginOrder extends CBOrder { private static final long serialVersionUID = 1L; private String name; private String password; public CBLoginOrder(String name, String password){ this.name = name; this.password = password; } public String getName(){ return this.name; } public String getPassword(){ return this.password; } } Faunis/src/communication/Map.java0000644000175000017500000000220112060472556016037 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication; public class Map { private String name; private int width; private int height; public Map(String name, int width, int height) { this.name = name; this.width = width; this.height = height; } public String getName() { return name; } public int getWidth() { return width; } public int getHeight() { return height; } } Faunis/src/communication/movement/0000775000175000017500000000000012062730610016306 5ustar useruserFaunis/src/communication/movement/MovingTask.java0000644000175000017500000000706712061420306021240 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.movement; import java.awt.Point; import java.util.TimerTask; import communication.enums.Direction; public abstract class MovingTask extends TimerTask { protected Object runningMutexKey; protected boolean stopRunning; protected Mover parent; protected Moveable moveable; public MovingTask(Mover parent, Moveable moveable) { this.parent = parent; this.moveable = moveable; this.runningMutexKey = new Object(); this.stopRunning = false; } /** Locks moveable, runningMutexKey or moving-list, animation-list, moveable */ @Override public void run() { // move moveable to target and // unregister at parent when target reached /* PROBLEM: On the client side, I want to call tryStopAnimation() in the unregisterMover() method. But that forces me to first synchronise on the locked resources there before I synchronise on moveable. */ synchronized(moveable) { if (!this.isMovementFinished()) { this.move(); return; } } // else: Object[] lists = parent.parent.getSynchroStuffForMoverStop(); assert(lists != null); if (lists.length == 1) { synchronized(lists[0]) { synchronized(moveable) { System.out.println("Synchronized on movingPlayerGraphics," +" moveable."); if (this.isMovementFinished()) parent.stopAndUnregister(); } } } else if (lists.length == 2) { synchronized(lists[0]) { synchronized(lists[1]) { System.out.println("Synchronized on movingPlayerGraphics," +" animatedPlayerGraphics, moveable."); synchronized(moveable) { if (this.isMovementFinished()) parent.stopAndUnregister(); } } } } else { throw new RuntimeException("MovingTask: Lists array is of strange size!"); } } protected abstract boolean isMovementFinished(); protected abstract void move(); public void stop() { parent.timer.cancel(); synchronized(runningMutexKey) { this.stopRunning = true; } synchronized(moveable) { moveable.resetPath(); } } public static Direction deltaToDirection(int deltaX, int deltaY) { if (Math.abs(deltaX) >= Math.abs(deltaY)) { if (deltaX < 0) return Direction.left; else if (deltaX > 0) return Direction.right; else return null; } else { if (deltaY < 0) return Direction.up; else if (deltaY > 0) return Direction.down; else return null; } } public static Point directionToDelta(Direction direction) { if (direction == null) return new Point(0,0); switch(direction) { case left: return new Point(-1,0); case right: return new Point(1,0); case up: return new Point(0,-1); case down: return new Point(0,1); } throw new RuntimeException("directionToDelta: Unknown direction!"); } } Faunis/src/communication/movement/MoverManager.java0000644000175000017500000000164312060472556021550 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.movement; public interface MoverManager { public void unregisterMover(Moveable forMoveable); public Object[] getSynchroStuffForMoverStop(); } Faunis/src/communication/movement/Pathfinder.java0000644000175000017500000000150112061577556021251 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.movement; public class Pathfinder { // TODO } Faunis/src/communication/movement/SoftMovingTask.java0000644000175000017500000000640412061600122022062 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.movement; import java.awt.Point; import client.Client; import client.ClientSettings; import client.PlayerGraphics; import communication.enums.Direction; /** For the client side: Moves the player along the path, but between adjusting * the coordinates, special values (deltaLevel) are also set, such that the * animation looks softer. Therefore it needs more (frequent) calls of move() * than RoughMovingTask, and the coordinates are not changed with every call. */ public class SoftMovingTask extends MovingTask { public SoftMovingTask(Mover parent, Moveable moveable) { super(parent, moveable); // TODO Auto-generated constructor stub } @Override protected boolean isMovementFinished() { return (moveable.getPath().isEmpty()); } @Override protected void move() { synchronized(moveable) { synchronized(runningMutexKey) { if (stopRunning) return; PlayerGraphics playerGraphics = (PlayerGraphics) moveable; assert(playerGraphics != null); ClientSettings settings = ((Client)(parent.parent)).getClientSettings(); int deltaLevelAmplitude = settings.deltaLevelAmplitude(); Path path = playerGraphics.getPath(); assert(path != null); int deltaLevel = playerGraphics.getDeltaLevel(); Point nextPoint = path.top(); //System.out.println("deltaLevel="+deltaLevel+", nextPoint="+nextPoint); assert(!(deltaLevel == 0 && nextPoint == null)); // We know where to go to, // and we also know the deltaLevel deltaLevel++; if (deltaLevel == 0) { playerGraphics.setDeltaLevel(deltaLevel); // stop movement if there's no further waypoint if (nextPoint == null) { // stop movement // playerGraphics.resetPath(); return; } } else if (deltaLevel == 1) { // adapt direction to next waypoint Direction newDirection = MovingTask.deltaToDirection( nextPoint.x-playerGraphics.getX(), nextPoint.y-playerGraphics.getY()); if (newDirection != null) playerGraphics.setDirection(newDirection); playerGraphics.setDeltaLevel(deltaLevel); } else if (deltaLevel > deltaLevelAmplitude) { // move over to the next field and remove waypoint from path deltaLevel = -deltaLevelAmplitude; playerGraphics.setDeltaLevel(deltaLevel); assert(nextPoint != null); playerGraphics.moveAbsolute(nextPoint.x, nextPoint.y, false); path.pop(); } else { playerGraphics.setDeltaLevel(deltaLevel); } } } } } Faunis/src/communication/movement/Path.java0000644000175000017500000000406112061577512020055 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.movement; import java.awt.Point; import java.io.Serializable; import java.util.LinkedList; /** FIFO-queue of coordinates along which a moveable can be moved. */ public class Path implements Serializable { private static final long serialVersionUID = 1L; LinkedList steps; public Path() { steps = new LinkedList(); } /** deep copy */ public Path copy() { Path result = new Path(); for (Point step : this.steps) { result.push((Point)step.clone()); } return result; } public void push(Point step) { steps.add(step); } /** Removes the next waypoint from this path and returns it, * or returns null if this path is empty. */ public Point pop() { if (steps.isEmpty()) return null; else return steps.pop(); } /** Returns the next waypoint or null if path is empty */ public Point top() { return steps.peek(); } public boolean isEmpty() { return steps.isEmpty(); } @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(); for (Point step : steps) { stringBuilder.append("("); stringBuilder.append(step.x); stringBuilder.append(","); stringBuilder.append(step.y); stringBuilder.append(")"); } return stringBuilder.toString(); } } Faunis/src/communication/movement/PathFactory.java0000644000175000017500000000320512060472556021405 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.movement; import java.awt.Point; import communication.Map; public class PathFactory { public static Path createAirlinePath(int fromX, int fromY, int toX, int toY) { Path result = new Path(); int currentX = fromX; int currentY = fromY; while (currentX != toX || currentY != toY) { int deltaX = toX-currentX; int deltaY = toY-currentY; if (Math.abs(deltaX) > Math.abs(deltaY)) { currentX += Math.signum(deltaX); Point point = new Point(currentX, currentY); result.push(point); } else { currentY += Math.signum(deltaY); Point point = new Point(currentX, currentY); result.push(point); } } assert(!result.isEmpty()); System.out.println("Path=" + result.toString()); return result; } /* public static Path createShortestPath(Map map, int fromX, int fromY, int toX, int toY) { // TODO } */ } Faunis/src/communication/movement/RoughMovingTask.java0000644000175000017500000000330312061600142022230 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.movement; import java.awt.Point; /** For the server side: Moves the Player in whole steps along the path * without any intermediate animation adjustments like in SoftMovingTask. * Therefore, one call of move() = one field onward. */ public class RoughMovingTask extends MovingTask { public RoughMovingTask(Mover parent, Moveable moveable) { super(parent, moveable); } @Override protected boolean isMovementFinished() { return (moveable.getPath().isEmpty()); } @Override protected void move() { synchronized(moveable) { synchronized(runningMutexKey) { if (stopRunning) return; Path path = moveable.getPath(); assert(path != null); Point nextPoint = path.pop(); if (nextPoint == null) { // moveable.setPath(null); return; } moveable.moveAbsolute(nextPoint.x, nextPoint.y, true); // if (path.isEmpty()) moveable.setPath(null); } } } } Faunis/src/communication/movement/Moveable.java0000644000175000017500000000203212060472556020710 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.movement; public interface Moveable { public boolean hasPath(); public void resetPath(); public int getX(); public int getY(); public void moveAbsolute(int x, int y, boolean adaptDirection); public Path getPath(); public void setPath(Path path); } Faunis/src/communication/movement/Mover.java0000644000175000017500000000372712060472556020262 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.movement; import java.util.Timer; public class Mover { protected MoverManager parent; protected Moveable moveable; protected Timer timer; protected MovingTask movingTask; protected long interval; /** PLEASE NOTE: You'll also have to create a MovingTask for this Mover * and assign it by calling Mover.setMovingTask()! Afterwards, don't forget * that this Mover isn't started yet. */ public Mover(MoverManager parent, Moveable moveable, long delay) { this.parent = parent; this.moveable = moveable; this.interval = delay; this.timer = new Timer(); } public void setMovingTask(MovingTask movingTask) { this.movingTask = movingTask; } /** Starts the MovingTask. Has to be explicitely called, * as that isn't done automatically.
* HINT: Doesn't register this Mover at the parent, because that must * already happen while creating the Mover. */ public void start() { this.timer.scheduleAtFixedRate(movingTask, 0, interval); } public Moveable getMoveable() { return moveable; } public void stop() { this.movingTask.stop(); } public void stopAndUnregister() { this.stop(); parent.unregisterMover(this.moveable); } } Faunis/src/communication/enums/0000775000175000017500000000000012062730610015603 5ustar useruserFaunis/src/communication/enums/BodyPart.java0000644000175000017500000000174012061420306020167 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.enums; /** Determines the limb, for animation. "compact" is only * used if the class graphics are not limbed. */ public enum BodyPart { body, head, leftArm, rightArm, leftLeg, rightLeg, tail, compact } Faunis/src/communication/enums/Direction.java0000644000175000017500000000161112061577370020376 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.enums; /** Determines the direction in which a player is looking. */ public enum Direction { left, right, up, down } Faunis/src/communication/enums/AniCompoType.java0000644000175000017500000000167012061576674021040 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.enums; /** Determines if each frame of an animation is drawn as a whole (compact) * or composed of separate images for each limb (limbed). */ public enum AniCompoType { limbed, compact } Faunis/src/communication/enums/CharacterClass.java0000644000175000017500000000170412061577302021336 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.enums; /** Determines a character's class: * rodent, badger, bear, owl, deer, lynx, eagle */ public enum CharacterClass { rodens, meles, arctos, glaux, cervus, lynx, aguila } Faunis/src/communication/enums/ClientStatus.java0000644000175000017500000000162512061577344021106 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.enums; /** Determines the client's connection / game status. */ public enum ClientStatus { disconnected, loggedOut, noCharLoaded, exploring, fighting } Faunis/src/communication/enums/AniEndType.java0000644000175000017500000000172512061577106020461 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.enums; /** Determines what happens when an animation ends, if it should be repeated, * stay in the last frame (end) or revert to the default standing state (revert). */ public enum AniEndType { revert, repeat, end } Faunis/src/communication/enums/FaceExpression.java0000644000175000017500000000162012061577440021372 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package communication.enums; /** Determines possible facial expressions for a player. */ public enum FaceExpression { normal, happy, sad, angry, surprised, tired, sick } Faunis/src/client/0000775000175000017500000000000012062730610013065 5ustar useruserFaunis/src/client/AnimatorManager.java0000644000175000017500000000160512060472074017002 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; public interface AnimatorManager { public void unregisterAnimator(Animateable animateable); public Object getSynchroStuffForAnimatorStop(); } Faunis/src/client/MessageType.java~0000644000175000017500000000146412062726756016377 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; public enum MessageType { error, system, whisper, broadcast } Faunis/src/client/GameWindow.java0000644000175000017500000002222512062201130015760 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTextPane; import javax.swing.text.BadLocationException; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledDocument; import communication.enums.ClientStatus; import communication.enums.Direction; import communication.movement.MovingTask; public class GameWindow extends GraphWin { protected Client parent; private JPanel commandPanel; private JScrollPane loggingScrollPane; private JTextPane loggingTextPane; private StyledDocument loggingDocument; private JButton commandSendButton; protected JTextField commandEdit; private SimpleAttributeSet errorTextStyle; private SimpleAttributeSet systemTextStyle; private SimpleAttributeSet whisperTextStyle; private SimpleAttributeSet oldCommandTextStyle; private SimpleAttributeSet broadcastTextStyle; public GameWindow(Client parent, int width, int height, String title) { super(width, height, title); this.parent = parent; errorTextStyle = new SimpleAttributeSet(); StyleConstants.setForeground(errorTextStyle, Color.red); systemTextStyle = new SimpleAttributeSet(); StyleConstants.setForeground(systemTextStyle, new Color(0, 120, 120)); whisperTextStyle = new SimpleAttributeSet(); StyleConstants.setForeground(whisperTextStyle, Color.blue); oldCommandTextStyle = new SimpleAttributeSet(); StyleConstants.setForeground(oldCommandTextStyle, Color.gray); broadcastTextStyle = new SimpleAttributeSet(); StyleConstants.setForeground(broadcastTextStyle, new Color(140, 80, 0)); loggingTextPane = new JTextPane(); loggingTextPane.setEditable(false); loggingTextPane.setBackground(new Color(230, 230, 230)); loggingDocument = loggingTextPane.getStyledDocument(); assert(loggingDocument != null); loggingScrollPane = new JScrollPane(loggingTextPane); loggingScrollPane.setPreferredSize(new Dimension(100,100)); JPanel loggingPanel = new JPanel(new BorderLayout()); loggingPanel.add(BorderLayout.CENTER, loggingScrollPane); commandEdit = new JTextField(); commandEdit.setPreferredSize(new Dimension(300,25)); commandSendButton = new JButton("Send"); commandSendButton.addActionListener(new CommandSendButtonListener()); commandPanel = new JPanel(); commandPanel.add(commandEdit); commandPanel.add(commandSendButton); JPanel southPanel = new JPanel(new BorderLayout()); southPanel.add(BorderLayout.CENTER, loggingPanel); southPanel.add(BorderLayout.SOUTH, commandPanel); win.getRootPane().setDefaultButton(commandSendButton); win.getContentPane().add(BorderLayout.SOUTH, southPanel); drawingPanel.setPreferredSize(new Dimension(width, height)); win.pack(); System.out.println("packed"); } @Override /** locks parent.clientStatus, (parent.currentPlayers; playerGraphics) * redraws Backbuffer (please call repaint() to copy it to the front) */ public void draw() { graph.setColor(Color.green); graph.fillRect(0, 0, img.getWidth(), img.getHeight()); Point mausPos = this.mousePos(); if (mausPos == null) mausPos = new Point(0,0); graph.setColor(Color.black); graph.drawRect(mausPos.x, mausPos.y, 100, 100); // depending on Client.clientStatus, other things have to be drawn synchronized(parent.getClientStatus()) { ClientStatus status = parent.getClientStatus(); if (status == ClientStatus.exploring || status == ClientStatus.fighting) { // draw grid: drawFieldGrid(); // write map and player name: writeMapAndPlayerInfo(); // draw all player graphics: drawAllPlayers(); } // draw clientStatus: drawClientStatus(); } } private void drawFieldGrid() { graph.setColor(Color.lightGray); int width = img.getWidth(); int height = img.getHeight(); int fieldWidth = parent.getClientSettings().fieldWidth(); int fieldHeight = parent.getClientSettings().fieldHeight(); int maxRow = height / fieldHeight; int maxColumn = width / fieldWidth; // draw horizontal lines: for (int y = 0; y < maxRow; y++) { graph.drawRect(0, y*fieldHeight, width, 0); } // draw vertical lines: for (int x = 0; x < maxColumn; x++) { graph.drawRect(x*fieldWidth, 0, 0, height); } } private void writeMapAndPlayerInfo() { String mapName = parent.getCurrentMapName(); String playerName = parent.getCurrentPlayerName(); graph.setColor(Color.black); if (mapName != null) graph.drawString(mapName, 10, 20); if (playerName != null) { PlayerGraphics player = parent.getPlayerGraphics(playerName); int x = player.getX(); int y = player.getY(); graph.drawString(playerName, 10, 30); graph.drawString("("+x+","+y+")", 10, 40); } } private void drawClientStatus() { ClientStatus status = parent.getClientStatus(); graph.setColor(Color.black); graph.drawString(status.toString(), 10, 10); } /** locks currentPlayers; einzelne playerGraphics * Draw all characters */ private void drawAllPlayers() { ArrayList allPlayerGraphics = parent.getAllGraphicsToDraw(); for (PlayerGraphics playerGraphics : allPlayerGraphics) { synchronized(playerGraphics) { Point offset = calculateDrawingOffset(playerGraphics); String playerName = playerGraphics.getName(); int playerNameWidth = graph.getFontMetrics().stringWidth(playerName); graph.setColor(Color.black); graph.drawString(playerName, offset.x - playerNameWidth/2, offset.y + 15); int frameIndex = playerGraphics.getFrame(); playerGraphics.draw(graph, offset.x, offset.y, frameIndex); } } } private Point calculateDrawingOffset(PlayerGraphics playerGraphics) { ClientSettings clientSettings = parent.getClientSettings(); int numDeltaLevels = clientSettings.numberOfDeltaLevelStates(); int fieldWidth = clientSettings.fieldWidth(); int fieldHeight = clientSettings.fieldHeight(); Direction direction = playerGraphics.getDirection(); Point delta = MovingTask.directionToDelta(direction); int deltaHoriz = (fieldWidth/numDeltaLevels) * delta.x; int deltaVert = (fieldHeight/numDeltaLevels) * delta.y; int deltaLevel = playerGraphics.getDeltaLevel(); int fieldX = playerGraphics.getX(); int fieldY = playerGraphics.getY(); // calculate resulting coordinates: int offsetX = fieldWidth/2 + fieldWidth * fieldX + deltaLevel*deltaHoriz; int offsetY = fieldHeight/2 + fieldHeight * fieldY + deltaLevel*deltaVert; return new Point(offsetX, offsetY); } protected class CommandSendButtonListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { String command = commandEdit.getText(); logOldCommandMessage(command); if (command.length() > 0 && command.startsWith("/")) { String[] commandSplit = command.split(" "); assert(commandSplit.length > 0); String commandPrefix = commandSplit[0]; String[] commandRest = new String[commandSplit.length-1]; for (int i = 1; i < commandSplit.length; i++) { commandRest[i-1] = commandSplit[i]; } // evaluate command: boolean success = parent.parseCommand(commandPrefix, commandRest); if (success) commandEdit.setText(null); } } } private void logMessage(String message, SimpleAttributeSet set) { try { loggingDocument.insertString(loggingDocument.getLength(), message+"\n", set); this.loggingTextPane.setCaretPosition(loggingDocument.getLength()); } catch (BadLocationException e) { e.printStackTrace(); System.out.println("Error appending a message to the loggingPane!"); } } public void logErrorMessage(String message) { logMessage(message, errorTextStyle); } public void logWhisperMessage(String message) { logMessage(message, whisperTextStyle); } public void logOldCommandMessage(String message) { logMessage(message, oldCommandTextStyle); } public void logBroadcastMessage(String message) { logMessage(message, broadcastTextStyle); } public void logSystemMessage(String message) { logMessage(message, systemTextStyle); } } Faunis/src/client/ClientSettings.java0000644000175000017500000000527712061602254016701 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; import java.io.File; public class ClientSettings { private String classPath; // paths are declared in constructor below; private String clientDataPath; // NOTE: All paths must end in "/" private String playerGraphicsPath; private String imageFileEnding = ".png"; // must begin with a fullstop! private int fieldWidth = 20; private int fieldHeight = 14; private int deltaLevelAmplitude = 2; private String host = null; // the hostname, or null for loopback private int port = 1024; // the port through which to connect to the server private int frameRate = 20; // frames per second public ClientSettings() { try { classPath = getClass().getProtectionDomain(). getCodeSource().getLocation().toURI().getPath(); } catch (Exception e) { e.printStackTrace(); return; } //classPath = classPath.substring(1); // Windows error only? File classPathFile = new File(classPath); String parentPath = classPathFile.getParent()+"/"; clientDataPath = parentPath+"clientData/"; playerGraphicsPath = clientDataPath+"playerGraphics/"; } public String playerGraphicsPath() { return playerGraphicsPath; } public String imageFileEnding() { return imageFileEnding; } public int fieldWidth() { return fieldWidth; } public int fieldHeight() { return fieldHeight; } public int deltaLevelAmplitude() { return deltaLevelAmplitude; } public int numberOfDeltaLevelStates() { return 2*deltaLevelAmplitude+1; } public String host() { return host; } public int port() { return port; } public int frameRate() { return frameRate; } public int delayBetweenFrames() { return 1000 / frameRate; } public String checkPaths() { File playerGraphicsDir = new File(playerGraphicsPath); if (! (playerGraphicsDir.exists() && playerGraphicsDir.isDirectory())) { String error = "Player graphics directory "+playerGraphicsPath+" doesn't exist!"; System.out.println("WARNING: "+error); return error; } return null; } } Faunis/src/client/PlayerGraphics.java0000644000175000017500000001357212061420306016650 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; import java.awt.Graphics; import java.awt.Point; import java.util.List; import communication.GraphicalPlayerStatus; import communication.GraphicsContentManager; import communication.enums.AniCompoType; import communication.enums.BodyPart; import communication.enums.CharacterClass; import communication.enums.Direction; import communication.movement.Moveable; import communication.movement.MovingTask; import communication.movement.Path; /** Represents the graphics of a player. It can be completely created just from * the player's GraphicalPlayerStatus and the client's GraphicsContentManager. * Any additional fields here don't have to be stored at / distributed over * the server and can be filled of each client during construction of playerGraphics. */ public class PlayerGraphics implements Moveable, Animateable { private GraphicalPlayerStatus info; private Client parent; private int deltaLevel = 0; // between -1 and +1 private int frame = 0; public PlayerGraphics(GraphicalPlayerStatus info, Client parent) { this.info = info; this.parent = parent; } private Bone getBone(BodyPart part) { String animation; if (hasPath()) animation = "walk"; else if (info.currentEmote != null) animation = info.currentEmote; else animation = "stand"; return parent.getGraphicsContentManager(). getBone(info.type, animation, part, info.direction); } public void draw(Graphics drawOnto, int x, int y, int frameIndex) { // Decide whether we have a limbed or compact type GraphicsContentManager graphicsContentManager = parent.getGraphicsContentManager(); AniCompoType compoType = graphicsContentManager.getCompositionType(info.type); List orderList; if (compoType == AniCompoType.compact) { orderList = graphicsContentManager.getCompactDrawingOrder(); } else { orderList = graphicsContentManager. getDrawingOrders().get(this.getDirection()); } assert(orderList != null); drawRecursive(BodyPart.body, null, x, y, drawOnto, orderList, frameIndex); } private void drawRecursive(BodyPart currentPart, BodyPart sourcePart, int originX, int originY, Graphics drawOnto, List orderList, int frameIndex) { // we need sourcePart only for preventing going backwards recursively Bone currentBone = getBone(currentPart); if (currentBone == null) { System.out.println("Couldn't find bone for "+currentPart+"!"); } Point offset = currentBone.getConnectionOffset(currentPart, frameIndex); if (offset == null) { System.out.println("Couldn't find offset for "+currentPart+", frame "+frameIndex+"!"); } assert(offset != null); for (BodyPart toDraw : orderList) { for (BodyPart part : currentBone.getConnectionOffsets(frameIndex)) { if (part != sourcePart && part == toDraw) { Point partOffset = currentBone.getConnectionOffset(part, frameIndex); drawRecursive(part, currentPart, originX-(offset.x-partOffset.x), originY-(offset.y-partOffset.y), drawOnto, orderList, frameIndex); } if (toDraw == currentPart) { currentBone.draw(drawOnto, originX-offset.x, originY-offset.y, frameIndex); } } } } public CharacterClass getType() { return info.type; } @Override public Path getPath() { return info.path; } @Override public void setPath(Path path) { info.path = path; } @Override public int getX() { return info.x; } @Override public int getY() { return info.y; } @Override public void resetPath() { info.path = null; this.deltaLevel = 0; System.out.println("Reset path."); } @Override public void resetEmote() { info.currentEmote = null; this.frame = 0; System.out.println("Set frame to 0."); } public int getDeltaLevel() { return this.deltaLevel; } public void setDeltaLevel(int deltaLevel) { this.deltaLevel = deltaLevel; } @Override public boolean hasPath() { return info.hasPath(); } public String getName() { return info.name; } public Direction getDirection() { return info.direction; } public void setDirection(Direction direction) { if (direction == null) System.out.println("ERROR: setDirection(null)"); assert(direction != null); info.direction = direction; } @Override public String getEmote() { return info.currentEmote; } @Override public void setEmote(String emote) { info.currentEmote = emote; } @Override public boolean hasEmote() { return info.hasEmote(); } @Override public int getFrame() { return frame; } @Override public void setFrame(int frame) { this.frame = frame; } /** Directly sets the coordinates of this playerGraphics to the given ones. * If given flag adaptDirection is set, sets the direction accordingly. */ @Override public void moveAbsolute(int x, int y, boolean adaptDirection) { if (adaptDirection) { Direction newDirection = MovingTask.deltaToDirection( x-info.x, y-info.y); if (newDirection != null) info.direction = newDirection; } info.x = x; info.y = y; } } Faunis/src/client/SwingMessageRunnable.java0000644000175000017500000000251112062726732020022 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; public class SwingMessageRunnable implements Runnable { private String message; private MessageType type; private GameWindow win; public SwingMessageRunnable(String message, MessageType type, GameWindow win) { this.message = message; this.type = type; this.win = win; } @Override public void run() { switch(type) { case error: win.logErrorMessage(message); break; case system: win.logSystemMessage(message); break; case whisper: win.logWhisperMessage(message); break; case broadcast: win.logBroadcastMessage(message); break; } } } Faunis/src/client/SwingMessageRunnable.java~0000644000175000017500000000114512062631610020210 0ustar useruserpackage client; public class SwingMessageRunnable implements Runnable { private String message; private MessageType type; private GameWindow win; public SwingMessageRunnable(String message, MessageType type, GameWindow win) { this.message = message; this.type = type; this.win = win; } @Override public void run() { switch(type) { case error: win.logErrorMessage(message); break; case system: win.logSystemMessage(message); break; case whisper: win.logWhisperMessage(message); break; case broadcast: win.logBroadcastMessage(message); break; } } } Faunis/src/client/MessageType.java0000644000175000017500000000146412062726764016200 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; public enum MessageType { error, system, whisper, broadcast } Faunis/src/client/AnimationData.java0000644000175000017500000000212212061420306016431 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; import communication.enums.AniEndType; public class AnimationData { public int numberOfFrames; public AniEndType endType; // AniCompoType not included since it's per CharacterClass, // not per Animation atm public AnimationData(int numberOfFrames, AniEndType endType) { this.numberOfFrames = numberOfFrames; this.endType = endType; } } Faunis/src/client/Animator.java0000644000175000017500000000721312061420306015500 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; import java.util.Timer; import java.util.TimerTask; import communication.enums.AniEndType; public class Animator { protected Object runningMutexKey; protected boolean stopRunning; protected AnimatorManager parent; protected Animateable animateable; private Timer timer; private AnimatingTask animatingTask; protected AniEndType endType; private long interval; protected int maxFrameIndex; /** Creates an Animator, but doesn't start it yet. */ public Animator(AnimatorManager parent, Animateable animateable, long delay, AniEndType endType, int maxFrameIndex) { this.parent = parent; this.animateable = animateable; this.timer = new Timer(); this.animatingTask = new AnimatingTask(); this.runningMutexKey = new Object(); this.stopRunning = false; this.endType = endType; this.interval = delay; this.maxFrameIndex = maxFrameIndex; } /** Starts the Animator. Has to be explicitely called, * as that isn't done automatically.
* HINT: Doesn't register this Animator at the Mapman, because that must * already happen while creating the Animator. */ public void start() { this.timer.scheduleAtFixedRate(animatingTask, 0, interval); } public Animateable getAnimateable() { return animateable; } /** asserts that at the method end, no * timerTask is running. */ public void stop() { this.timer.cancel(); synchronized(runningMutexKey) { stopRunning = true; } synchronized(animateable) { animateable.resetEmote(); } } public void stopAndUnregister() { this.stop(); parent.unregisterAnimator(animateable); } protected class AnimatingTask extends TimerTask { @Override public void run() { // increase animateable's frame index and // unregister at parent when animation is over synchronized(animateable) { if (!this.isAnimationFinished()) { this.animate(); return; } } // else: Object list = parent.getSynchroStuffForAnimatorStop(); assert(list != null); synchronized(list) { synchronized(animateable) { if (this.isAnimationFinished()) stopAndUnregister(); } } } private boolean isAnimationFinished() { int frame = animateable.getFrame(); if (frame >= maxFrameIndex && endType == AniEndType.revert) return true; return false; } private void animate() { synchronized(animateable) { synchronized(runningMutexKey) { if (stopRunning) return; int frame = animateable.getFrame(); switch (endType) { case repeat: System.out.print("Increase frame from "+frame); frame++; if (frame > maxFrameIndex) frame = 0; System.out.println(" to "+frame); animateable.setFrame(frame); break; case revert: case end: if (frame < maxFrameIndex) { System.out.print("Increase frame from "+frame+" to "+(frame+1)); animateable.setFrame(frame+1); } break; } } } } } } Faunis/src/client/Bone.java0000644000175000017500000000703012061420306014606 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Set; import javax.imageio.ImageIO; import communication.enums.BodyPart; public class Bone { private ArrayList images; private ArrayList> connectionOffsets; private static ColourBoneTranslator translator = ColourBoneTranslator.getInstance(); private boolean isAnimation; public Bone(String filePath) { images = new ArrayList(); try { File graphicFile = new File(filePath); BufferedImage image = ImageIO.read(graphicFile); images.add(image); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Couldn't load picture!"); } isAnimation = false; connectionOffsets = new ArrayList>(); readConnectionOffsets(); } public Bone(String animationPrefix, String fileEnding, int maxFrameIndex) { images = new ArrayList(); for (int frameIndex = 0; frameIndex <= maxFrameIndex; frameIndex++) { File frameFile = new File(animationPrefix+frameIndex+fileEnding); try { BufferedImage frame = ImageIO.read(frameFile); images.add(frame); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("Couldn't load frame!"); } // TODO } isAnimation = true; connectionOffsets = new ArrayList>(); readConnectionOffsets(); } public boolean isAnimation() { return isAnimation; } public void readConnectionOffsets() { for (int frameIndex = 0; frameIndex < images.size(); frameIndex++) { BufferedImage image = images.get(frameIndex); HashMap offsets = new HashMap(); for (int y = 0; y < image.getHeight(); y++) { for (int x = 0; x < image.getWidth(); x++) { Color readColour = new Color(image.getRGB(x, y), true); BodyPart part = translator.translate(readColour); if (part != null) { offsets.put(part, new Point(x, y)); } } } connectionOffsets.add(offsets); } } public Point getConnectionOffset(BodyPart part, int frameIndex) { assert(connectionOffsets.get(frameIndex).containsKey(part)); return connectionOffsets.get(frameIndex).get(part); } public Set getConnectionOffsets(int frameIndex) { return connectionOffsets.get(frameIndex).keySet(); } public BufferedImage getImage(int frameIndex) { return images.get(frameIndex); } public void draw(Graphics drawOnto, int x, int y, int frameIndex) { drawOnto.drawImage(this.images.get(frameIndex), x, y, null); } } Faunis/src/client/GraphWin.java0000644000175000017500000000646712062201146015457 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; import java.awt.*; import java.awt.image.BufferedImage; import java.awt.Graphics; import javax.swing.*; public abstract class GraphWin { public boolean repaint = false; public JFrame win; public DrawingPanel drawingPanel; public BufferedImage img; public Graphics graph; private int width; private int height; @SuppressWarnings("unused") private String title; public GraphWin(int width, int height, String title){ // initialize GraphWin this.width = width; this.height = height; this.title = title; this.drawingPanel = new DrawingPanel(); drawingPanel.setIgnoreRepaint(true); this.img = new BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_RGB); this.graph = this.img.createGraphics(); drawingPanel.parent = this; win = new JFrame(); win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); win.setSize(width, height); win.setResizable(false); win.setTitle(title); win.getContentPane().add(BorderLayout.CENTER, drawingPanel); } public void show(){ win.setVisible(true); } public void hide(){ win.setVisible(false); } public void setTitle(String title){ win.setTitle(title); } public String getTitle(){ return win.getTitle(); } public int getWidth(){ return this.width; } public int getHeight(){ return this.height; } public abstract void draw(); public Point mousePos(){ return drawingPanel.getMousePosition(); } public void repaint(){ drawingPanel.repaint(); } public void setColor(Color c){ graph.setColor(c); } public void setColor(int red, int green, int blue){ Color temp = new Color(red, green, blue); graph.setColor(temp); } public Color getColor(){ return graph.getColor(); } public int getRed(){ return graph.getColor().getRed(); } public int getGreen(){ return graph.getColor().getGreen(); } public int getBlue(){ return graph.getColor().getBlue(); } public void clear(){ Color temp = graph.getColor(); graph.setColor(Color.white); graph.fillRect(0, 0, this.getWidth(), this.getHeight()); graph.setColor(temp); } public static void delay(long millis){ try { Thread.sleep(millis); } catch (InterruptedException e) { System.out.println("could not delay!"); e.printStackTrace(); } } public class DrawingPanel extends JPanel{ private static final long serialVersionUID = 1L; public GraphWin parent; @Override public void paintComponent(Graphics g){ super.paintComponent(g); g.drawImage(parent.img, 0, 0, this); } } } Faunis/src/client/Animateable.java0000644000175000017500000000170712061157302016135 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; public interface Animateable { public boolean hasEmote(); public String getEmote(); public void setEmote(String emote); public void resetEmote(); public int getFrame(); public void setFrame(int frame); } Faunis/src/client/Client.java0000644000175000017500000006032412062632226015155 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationTargetException; import java.net.Socket; import java.util.ArrayList; import java.util.HashMap; import javax.swing.SwingUtilities; import communication.GraphicalPlayerStatus; import communication.GraphicsContentManager; import communication.MapInfo; import communication.butlerToClientOrders.*; import communication.clientToButlerOrders.*; import communication.enums.AniEndType; import communication.enums.ClientStatus; import communication.movement.Moveable; import communication.movement.Mover; import communication.movement.MoverManager; import communication.movement.MovingTask; import communication.movement.SoftMovingTask; public class Client implements MoverManager, AnimatorManager { private Object connectionModiMutexKey; private boolean connectionModiOccupied; private ClientStatus clientStatus; private ClientSettings clientSettings; private GraphicsContentManager graphicsContentManager; private Socket socket; private ObjectOutputStream output; protected ObjectInputStream input; private GameWindow win; private String activePlayerName; private String currentMapName; private HashMap currentPlayers; private HashMap movingPlayerGraphics; private HashMap animatedPlayerGraphics; private Thread serverThread; // steadily replies to requests from the server side private ServerRunnable serverRunnable; // the serverThread's job protected boolean stopServerThread; public final static FileFilter directoryFilter = new FileFilter() { @Override public boolean accept(File file) { return file.isDirectory(); } }; public static void main(String[] args){ new Client().init(); } private void run(){ while(true){ GraphWin.delay(clientSettings.delayBetweenFrames()); win.draw(); win.repaint(); } } public void init() { // setup (dis-)connection management stuff: this.connectionModiMutexKey = new Object(); this.connectionModiOccupied = false; this.stopServerThread = false; // set initial clientStatus: clientStatus = ClientStatus.disconnected; // create game window: /* NOTE: Swing is single-threaded. And as I have learned, it * causes problems even when only one thread is accessing it at all. * So we introduce the "good" / complicated way to deal with Swing * stuff: Runnables for the Event Dispatching Thread (EDT). */ try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { win = new GameWindow(Client.this, 800, 500, "Faunis"); win.show(); } }); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } logSystemMessage("Welcome to Faunis!"); logSystemMessage("Copyright 2012 Simon Ley alias \"skarute\""); logSystemMessage("Licensed under GNU AGPL v3 or later"); // load client settings: clientSettings = new ClientSettings(); // check if clientSettings paths exist: String pathErrorMsg = clientSettings.checkPaths(); if (pathErrorMsg != null) logErrorMessage(pathErrorMsg); // load data: graphicsContentManager = new GraphicsContentManager( clientSettings.playerGraphicsPath(), clientSettings.imageFileEnding()); graphicsContentManager.loadResourcesForClient(); currentPlayers = new HashMap(); this.movingPlayerGraphics = new HashMap(); this.animatedPlayerGraphics = new HashMap(); this.serverRunnable = new ServerRunnable(this); connect(); this.run(); } public PlayerGraphics getPlayerGraphics(String name) { synchronized(currentPlayers) { assert(currentPlayers.containsKey(name)); return currentPlayers.get(name); } } public String getCurrentMapName() { return currentMapName; } public String getCurrentPlayerName() { return activePlayerName; } public ClientSettings getClientSettings() { return clientSettings; } @Override public Object[] getSynchroStuffForMoverStop() { return new Object[] {movingPlayerGraphics, animatedPlayerGraphics}; } @Override public Object getSynchroStuffForAnimatorStop() { return new Object[] {animatedPlayerGraphics}; } public GraphicsContentManager getGraphicsContentManager() { return graphicsContentManager; } public ClientStatus getClientStatus() { return clientStatus; } /** locks connectionModiMutexKey; clientStatus */ public boolean connect() { synchronized(connectionModiMutexKey) { if (connectionModiOccupied) { return false; } else { connectionModiOccupied = true; } } synchronized(clientStatus) { if (this.clientStatus != ClientStatus.disconnected) { logErrorMessage("Couldn't connect since clientStatus is not set to \"disconnected\"!"); connectionModiOccupied = false; return false; } assert(socket == null || socket.isClosed()); // create socket: try { this.socket = new Socket(clientSettings.host(), clientSettings.port()); } catch (Exception e) { logErrorMessage("Socket to game server couldn't be created! Reason: "+e.getLocalizedMessage()); connectionModiOccupied = false; return false; } System.out.println("Socket created."); // create input and output stream: System.out.println("Try to create input / output streams..."); try { this.input = new ObjectInputStream(this.socket.getInputStream()); this.output = new ObjectOutputStream(this.socket.getOutputStream()); } catch (IOException e) { e.printStackTrace(); logErrorMessage("Couldn't create input / output!"); connectionModiOccupied = false; return false; } clientStatus = ClientStatus.loggedOut; System.out.println("Input / output have been created."); System.out.println("Start serverThread..."); stopServerThread = false; assert(serverThread == null || !serverThread.isAlive()); this.serverThread = new Thread(this.serverRunnable, "client_serverThread"); this.serverThread.start(); connectionModiOccupied = false; return true; } } /** locks connectionModiMutexKey; clientStatus, currentPlayers, movingPlayerGraphics */ public boolean disconnect() { System.out.println("Client: called disconnect()"); synchronized(connectionModiMutexKey) { if (connectionModiOccupied) { System.out.println("Client: disconnect(): Connection is already being modified?"); return false; } else { connectionModiOccupied = true; } } synchronized(clientStatus) { if (this.clientStatus == ClientStatus.disconnected) { logErrorMessage("Client: Couldn't disconnect as clientStatus is already \"disconnected\""); connectionModiOccupied = false; return false; } // Cause serverThread to terminate assert(serverThread.isAlive()); stopServerThread = true; try { this.input.close(); } catch (IOException e) { e.printStackTrace(); System.out.println("Couldn't choke serverThread!"); } if (Thread.currentThread() != this.serverThread) { System.out.println("disconnect(): Caller isn't serverThread"); while (this.serverThread.isAlive()) {} assert(!serverThread.isAlive()); System.out.println("Client: serverThread terminated."); } else { System.out.println("disconnect(): Caller is serverThread"); } stopServerThread = false; unloadMap(); clientStatus = ClientStatus.disconnected; input = null; output = null; serverThread = null; connectionModiOccupied = false; System.out.println("Client: Connection to server terminated."); return true; } } // Server to client section: ################################################################# class ServerRunnable implements Runnable { private Client parent; public ServerRunnable(Client parent) { this.parent = parent; } @Override public void run() { // handle Order from parent.input: while (!stopServerThread) { Object read = null; try { read = parent.input.readObject(); } catch (IOException e) { logErrorMessage("Couldn't read anymore from server!"); if (!stopServerThread) disconnect(); System.out.println("serverRunnable ends."); return; } catch (ClassNotFoundException e) { e.printStackTrace(); System.out.println("ClassNotFoundException!"); } if (read != null && read instanceof BCOrder) parent.handleServerOrder((BCOrder)read); } System.out.println("serverRunnable ends."); } } /** locks movingPlayerGraphics, animatedPlayerGraphics, playerGraphics */ private void tryStopMovement(PlayerGraphics playerGraphics) { synchronized(movingPlayerGraphics) { synchronized(animatedPlayerGraphics) { synchronized(playerGraphics) { Mover mover = movingPlayerGraphics.get(playerGraphics); if (mover != null) { mover.stop(); unregisterMover(playerGraphics); // TODO: I think we can sum the above to mover.stopAndUnregister(); System.out.println("Movement stopped."); } } } } } /** locks animatedPlayerGraphics, playerGraphics
* Stops animation, removes emote from playerGraphics and resets frame counter. */ private void tryStopAnimation(PlayerGraphics playerGraphics) { synchronized(animatedPlayerGraphics) { synchronized(playerGraphics) { Animator animator = animatedPlayerGraphics.get(playerGraphics); if (animator != null) { animator.stop(); unregisterAnimator(playerGraphics); // TODO: I think we can sum the above to animator.stopAndUnregister(); System.out.println("Animation stopped."); } } } } public void handleServerOrder(BCOrder order) { assert(order != null); if (order instanceof BCAddCharOrder) { addChar((BCAddCharOrder) order); } else if (order instanceof BCChangeCharOrder) { changeChar((BCChangeCharOrder) order); } else if (order instanceof BCRemoveCharOrder) { removeChar((BCRemoveCharOrder) order); } else if (order instanceof BCSetMapOrder) { setMap((BCSetMapOrder) order); } else if (order instanceof BCSetClientStatusOrder) { setClientStatus((BCSetClientStatusOrder) order); } else if (order instanceof BCErrorMessageOrder) { logErrorMessage((BCErrorMessageOrder) order); } else if (order instanceof BCSystemMessageOrder) { logSystemMessage((BCSystemMessageOrder) order); } else if (order instanceof BCChatMessageOrder) { showChatMessage((BCChatMessageOrder) order); } else { System.out.println("Received unknown server order!"); } // TODO: Implement the handling of further server orders } public void showChatMessage(BCChatMessageOrder order) { if (order.isBroadcast()) { SwingUtilities.invokeLater( new SwingMessageRunnable(order.getFromName()+": " +order.getMessage(), MessageType.broadcast, win)); } else { SwingUtilities.invokeLater( new SwingMessageRunnable(order.getFromName()+": " +order.getMessage(), MessageType.whisper, win)); } } public void logErrorMessage(BCErrorMessageOrder order) { logErrorMessage(order.getMessage()); } public void logErrorMessage(String errorMessage) { SwingUtilities.invokeLater( new SwingMessageRunnable("ERROR: "+errorMessage, MessageType.error, win)); } public void logSystemMessage(BCSystemMessageOrder order) { logSystemMessage(order.getMessage()); } public void logSystemMessage(String systemMessage) { SwingUtilities.invokeLater( new SwingMessageRunnable(systemMessage, MessageType.system, win)); } /** locks currentPlayers, movingPlayerGraphics, playerGraphics */ public void addChar(BCAddCharOrder order) { GraphicalPlayerStatus status = order.getGraphStatus(); PlayerGraphics playerGraphics = new PlayerGraphics(status, this); String playerName = order.getPlayerName(); // Add playerGraphics: synchronized(currentPlayers) { assert(! currentPlayers.containsKey(playerName)); currentPlayers.put(playerName, playerGraphics); } // If the new playerGraphics is moving, create Mover and add it: if (playerGraphics.hasPath()) { tryStartMovement(playerGraphics); } else if (playerGraphics.hasEmote()) { tryStartAnimation(playerGraphics, playerGraphics.getEmote()); } } /** locks currentPlayers; movingPlayerGraphics; currentPlayers */ public void removeChar(BCRemoveCharOrder order) { String playerName = order.getPlayerName(); PlayerGraphics playerGraphics; synchronized(currentPlayers) { assert(currentPlayers.containsKey(playerName)); playerGraphics = currentPlayers.get(playerName); } // Stop possible earlier animation and movement: tryStopMovement(playerGraphics); tryStopAnimation(playerGraphics); synchronized(currentPlayers) { assert(currentPlayers.containsKey(playerName)); currentPlayers.remove(playerName); } } /** locks currentPlayers; movingPlayerGraphics; currentPlayers */ public void changeChar(BCChangeCharOrder order) { GraphicalPlayerStatus status = order.getGraphStatus(); PlayerGraphics playerGraphics = new PlayerGraphics(status, this); String playerName = order.getPlayerName(); PlayerGraphics oldGraphics = null; synchronized(currentPlayers) { assert(currentPlayers.containsKey(playerName)); oldGraphics = currentPlayers.get(playerName); } System.out.println("old x="+oldGraphics.getX()+", y="+oldGraphics.getY()); System.out.println("new x="+playerGraphics.getX()+", y="+playerGraphics.getY()); // If playerGraphics was moving before, remove Mover: tryStopMovement(oldGraphics); tryStopAnimation(oldGraphics); // see NOTE above // Replace playerGraphics synchronized(currentPlayers) { assert(currentPlayers.containsKey(playerName)); currentPlayers.put(playerName, playerGraphics); } // If the new playerGraphics is moving, create Mover and add it: if (playerGraphics.hasPath()) { tryStartMovement(playerGraphics); } else if (playerGraphics.hasEmote()) { tryStartAnimation(playerGraphics, playerGraphics.getEmote()); } } /** locks movingPlayerGraphics, animatedPlayerGraphics, playerGraphics
* Also starts walking animation. */ public void tryStartMovement(PlayerGraphics playerGraphics) { synchronized(movingPlayerGraphics) { synchronized(animatedPlayerGraphics) { synchronized(playerGraphics) { // TODO: assert that there doesn't already exist a Mover! if (movingPlayerGraphics.containsKey(playerGraphics)) { System.out.println("There already exists a Mover!"); return; } if (playerGraphics.hasPath() && !playerGraphics.getPath().isEmpty()) { System.out.print("Start movement..."); int numDeltaLevels = clientSettings.numberOfDeltaLevelStates(); Mover mover = new Mover(this, playerGraphics, 500/numDeltaLevels);//TODO: Zeiteinheit MovingTask movingTask = new SoftMovingTask(mover, playerGraphics); mover.setMovingTask(movingTask); movingPlayerGraphics.put(playerGraphics, mover); mover.start(); System.out.println(" movement started. Start animation too..."); tryStartAnimation(playerGraphics, "walk"); } } } } } /** locks animatedPlayerGraphics, playerGraphics
* Starts the given animation. */ public void tryStartAnimation(PlayerGraphics playerGraphics, String animation) { synchronized(animatedPlayerGraphics) { synchronized(playerGraphics) { // assert that there doesn't already exist an Animator! if (animatedPlayerGraphics.containsKey(playerGraphics)) { System.out.println("There already exists a Animator!"); return; } System.out.print("Start animation..."); AnimationData animationData = graphicsContentManager.getAnimationData(playerGraphics.getType(), animation); AniEndType endType = animationData.endType; int maxFrameIndex = animationData.numberOfFrames-1; // TODO: Get animation interval Animator animator = new Animator(this, playerGraphics, 100, endType, maxFrameIndex); animatedPlayerGraphics.put(playerGraphics, animator); animator.start(); System.out.println(" animation started."); } } } /** locks currentPlayers, movingPlayerGraphics */ private void unloadMap() { synchronized(currentPlayers) { synchronized(movingPlayerGraphics) { for (String playerName : currentPlayers.keySet()) { PlayerGraphics playerGraphics = currentPlayers.get(playerName); tryStopMovement(playerGraphics); } currentPlayers.clear(); activePlayerName = null; currentMapName = null; } } } /** locks currentPlayers, movingPlayerGraphics
* A new map will be loaded: Remove all movements and * playerGraphics and register them anew from the MapInfo */ public void setMap(BCSetMapOrder order) { MapInfo mapInfo = order.getMapInfo(); synchronized(currentPlayers) { synchronized(movingPlayerGraphics) { unloadMap(); // everything is unloaded, now load: currentMapName = mapInfo.mapName; activePlayerName = order.getActivePlayerName(); for (String playerName2 : mapInfo.players.keySet()) { GraphicalPlayerStatus status = mapInfo.players.get(playerName2); PlayerGraphics playerGraphics = new PlayerGraphics(status, this); currentPlayers.put(playerName2, playerGraphics); tryStartMovement(playerGraphics); } } } } /** locks clientStatus, currentPlayers, movingPlayerGraphics */ public void setClientStatus(BCSetClientStatusOrder order) { ClientStatus newStatus = order.getNewStatus(); if (newStatus == ClientStatus.disconnected) { // Don't call disconnect() here as the serverRunnable cannot // force its termination at this point. Instead // we'll just close the input, causing this serverRunnable to // call disconnect() in its main loop where it can terminate. try { input.close(); } catch (IOException e) { e.printStackTrace(); System.out.println("Couldn't choke serverThread!"); } return; } synchronized(clientStatus) { if (( clientStatus == ClientStatus.exploring || clientStatus == ClientStatus.fighting) && newStatus != ClientStatus.exploring && newStatus != ClientStatus.fighting) { unloadMap(); } this.clientStatus = newStatus; } } // ################################################################################ /** locks clientStatus, output
* Tries to send given ClientOrder to the own Butler, and returns * the success thereof as a boolean.*/ public boolean sendOrder(CBOrder c){ synchronized(clientStatus) { if (clientStatus == ClientStatus.disconnected) { logErrorMessage("Client: Couldn't send order since there's no connection!"); return false; } assert(output != null); synchronized(output) { try { output.writeObject(c); } catch (IOException e) { logErrorMessage("Error while sending ClientOrder"); return false; } return true; } } } public boolean parseCommand(String commandPrefix, String[] commandSplitDetails) { if (commandPrefix.equals("/c")) { connect(); return true; } else if (commandPrefix.equals("/i") && commandSplitDetails.length >= 2) { String loginName = commandSplitDetails[0]; String loginPassword = commandSplitDetails[1]; sendOrder(new CBLoginOrder(loginName, loginPassword)); return true; } else if (commandPrefix.equals("/o")) { sendOrder(new CBLogoutOrder()); return true; } else if (commandPrefix.equals("/x")) { sendOrder(new CBDisconnectOrder()); return true; } else if (commandPrefix.equals("/w") && commandSplitDetails.length >= 2) { String receiver = commandSplitDetails[0]; String message = concatenateHelper(commandSplitDetails, 1); sendOrder(new CBChatOrder(message, receiver)); return true; } else if (commandPrefix.equals("/b") && commandSplitDetails.length >= 1) { String message = concatenateHelper(commandSplitDetails, 0); sendOrder(new CBChatOrder(message, null)); return true; } else if (commandPrefix.equals("/l")) { String playerName = commandSplitDetails[0]; sendOrder(new CBLoadPlayerOrder(playerName)); return true; } else if (commandPrefix.equals("/u")) { sendOrder(new CBUnloadPlayerOrder()); return true; } else if (commandPrefix.equals("/n") && commandSplitDetails.length >= 1) { String playerName = commandSplitDetails[0]; sendOrder(new CBCreatePlayerOrder(playerName)); return true; } else if (commandPrefix.equals("/m") && commandSplitDetails.length >= 2) { int walkX, walkY; try { walkX = Integer.parseInt(commandSplitDetails[0]); walkY = Integer.parseInt(commandSplitDetails[1]); } catch(NumberFormatException e) { logErrorMessage("Error while parsing the numbers."); return false; } sendOrder(new CBMoveOrder(walkX, walkY)); return true; } else if (commandPrefix.equals("/e")) { String emoteName = null; if (commandSplitDetails.length >= 1) { emoteName = commandSplitDetails[0]; } sendOrder(new CBTriggerEmoteOrder(emoteName)); return true; } else if (commandPrefix.equals("/s")) { sendOrder(new CBServerSourceOrder()); return true; } else { logErrorMessage("Command couldn't be interpreted."); return false; } // TODO: handle further commands } /** locks movingPlayerGraphics, animatedPlayerGraphics
* Unregisters the Mover for given playerGraphics after movement has stopped. * Also unregisters the Animator.
* Do not call this to stop movement, but call tryStopMovement() instead! */ @Override public void unregisterMover(Moveable moveable) { System.out.println("Unregistering Mover..."); assert(moveable instanceof PlayerGraphics); PlayerGraphics playerGraphics = (PlayerGraphics) moveable; synchronized(movingPlayerGraphics) { tryStopAnimation(playerGraphics); movingPlayerGraphics.remove(playerGraphics); } } /** locks animatedPlayerGraphics
* Unregisters the Animator for given playerGraphics after animation has * stopped.
Do not call this to stop animation, but call tryStopAnimation() instead! */ @Override public void unregisterAnimator(Animateable animateable) { assert(animateable instanceof PlayerGraphics); PlayerGraphics playerGraphics = (PlayerGraphics) animateable; synchronized(animatedPlayerGraphics) { animatedPlayerGraphics.remove(playerGraphics); } } /** locks currentPlayers */ public ArrayList getAllGraphicsToDraw() { ArrayList result = new ArrayList(); if (currentPlayers == null) return result; synchronized(currentPlayers) { for (PlayerGraphics playerGraphics : currentPlayers.values()) { result.add(playerGraphics); } } return result; } private static String concatenateHelper(String[] array, int startIndex) { assert(startIndex < array.length); StringBuilder message = new StringBuilder(); message.append(array[startIndex]); for (int i = startIndex+1; i < array.length; i++) { message.append(" "); message.append(array[i]); } return message.toString(); } } Faunis/src/client/ColourBoneTranslator.java0000644000175000017500000000341312061420306020045 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package client; import java.awt.Color; import java.util.HashMap; import communication.enums.BodyPart; public class ColourBoneTranslator { private HashMap colourToBone; private static ColourBoneTranslator instance; public static ColourBoneTranslator getInstance() { if (instance == null) instance = new ColourBoneTranslator(); return instance; } private ColourBoneTranslator() { colourToBone = new HashMap(); colourToBone.put(Color.MAGENTA, BodyPart.head); colourToBone.put(Color.ORANGE, BodyPart.body); colourToBone.put(Color.GRAY, BodyPart.tail); colourToBone.put(Color.GREEN, BodyPart.rightArm); colourToBone.put(Color.CYAN, BodyPart.leftArm); colourToBone.put(Color.RED, BodyPart.rightLeg); colourToBone.put(Color.BLUE, BodyPart.leftLeg); //colourToBone.put(Color.YELLOW, BodyPart.walkOffset); // Color.orange RGB: 255, 200, 0 } public BodyPart translate(Color pixelColour) { return colourToBone.get(pixelColour); } } Faunis/src/server/0000775000175000017500000000000012062730610013115 5ustar useruserFaunis/src/server/Player.java0000644000175000017500000000724412061420306015216 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server; import java.io.Serializable; import communication.GraphicalPlayerStatus; import communication.enums.CharacterClass; import communication.enums.Direction; import communication.movement.Moveable; import communication.movement.MovingTask; import communication.movement.Path; /** Represents a playable character on the server side. */ public class Player implements Serializable, Moveable { private static final long serialVersionUID = 1L; private String name; // unique player name private CharacterClass type; private String currentMapName; private String accountName; private int x; private int y; private Direction direction; private Path path; private String currentEmote; // do not store emotes of end type "revert" here! public Player(String name, CharacterClass type, String currentMapName, String accountName) { this.name = name; this.type = type; this.currentMapName = currentMapName; this.accountName = accountName; this.direction = Direction.down; this.x = 5; this.y = 5; this.path = null; } /** IMPORTANT: GraphicalPlayerStatus has to be independent from the player, * that means no shared references etc.! */ public GraphicalPlayerStatus getGraphicalPlayerStatus() { // TODO GraphicalPlayerStatus graphStatus = new GraphicalPlayerStatus(); graphStatus.name = this.name; graphStatus.type = this.type; graphStatus.direction = this.direction; graphStatus.path = (this.path == null)? null : this.path.copy(); graphStatus.currentEmote = this.currentEmote; // immutable :o] graphStatus.x = this.x; graphStatus.y = this.y; return graphStatus; } // getters and setters: public String getMapName() { return currentMapName; } public CharacterClass getType() { return type; } public String getAccountName() { return accountName; } public void setAccountName(String accountName) { this.accountName = accountName; } public String getName(){ return this.name; } public int getX() { return x; } public int getY() { return y; } public Path getPath() { return path; } public void setPath(Path path) { this.path = path; } public void resetPath() { this.path = null; } public boolean hasPath() { return (path != null); } public String getCurrentEmote() { return currentEmote; } public void setCurrentEmote(String emote) { currentEmote = emote; } public void resetEmote() { this.currentEmote = null; } public boolean isAnimating() { return (currentEmote != null); } public void moveAbsolute(int toX, int toY, boolean adaptDirection) { if (adaptDirection) { Direction newDirection = MovingTask.deltaToDirection( toX-this.x, toY-this.y); if (newDirection != null) this.direction = newDirection; } this.x = toX; this.y = toY; } public void setMapName(String mapName) { this.currentMapName = mapName; } } Faunis/src/server/MainServer.java0000644000175000017500000004602612061740004016036 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server; import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintWriter; import java.net.Socket; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import javax.swing.JFrame; import server.mapmanToButlerOrders.MBStopThreadOrder; import communication.GraphicsContentManager; import communication.Map; import communication.enums.CharacterClass; import communication.movement.Path; /** The main program; Holds all references and manages file access. */ public class MainServer { private ServerSettings serverSettings; private Reception reception; private List butlers; // To avoid deadlocks, these resources have to // be always locked from top to bottom private HashMap accnameToButler; private HashMap mapnameToMapman; private HashMap activePlayernameToPlayer; private HashMap loggedAccnameToAccount; private GraphicsContentManager graphicsContentManager; private HashSet allExistingPlayerNames; public final static FileFilter directoryFilter = new FileFilter() { @Override public boolean accept(File file) { return file.isDirectory(); } }; public static void main(String[] args) { MainServer server = new MainServer(); server.run(); } public void run() { System.out.println("Welcome to the Faunis server!"); System.out.println("Copyright 2012 Simon Ley alias \"skarute\""); System.out.println("Licensed under GNU AGPL v3 or later"); serverSettings = new ServerSettings(); butlers = new ArrayList(); accnameToButler = new HashMap(); mapnameToMapman = new HashMap(); activePlayernameToPlayer = new HashMap(); loggedAccnameToAccount = new HashMap(); System.out.println("account storage in "+serverSettings.accountPath()); // Check if serverSettings paths exist: serverSettings.checkPaths(); allExistingPlayerNames = loadAllExistingPlayerNames(); reception = new Reception(this, serverSettings.receptionPort()); System.out.println("Reception has been created."); JFrame control = new JFrame("MainServer"); control.setSize(200, 200); control.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); control.setVisible(true); // load content: graphicsContentManager = new GraphicsContentManager( serverSettings.playerGraphicsPath(), serverSettings.imageFileEnding()); graphicsContentManager.loadResourcesForServer(); // TODO // DEBUG - load testing content: String starterRegion = serverSettings.starterRegion(); Map starterMap = new Map(starterRegion, 50, 50); MapManager starterMapman = new MapManager(this, starterMap); synchronized(mapnameToMapman) { this.mapnameToMapman.put(starterRegion, starterMapman); } } public ServerSettings getServerSettings() { return serverSettings; } public GraphicsContentManager getGraphicsContentManager() { return graphicsContentManager; } /** locks mapnameToMapman */ public MapManager getMapman(String mapName) { synchronized(mapnameToMapman) { return mapnameToMapman.get(mapName); } } /** locks activePlayernameToPlayer
* returns the active Player instance with the given name */ public Player getActivePlayerByName(String playerName) { synchronized(activePlayernameToPlayer) { return activePlayernameToPlayer.get(playerName); } } /** locks activePlayerNameToPlayer; accNameToButler */ public Result getButlerByPlayerName(String playerName) { Player player = getActivePlayerByName(playerName); if (player == null) { String error = "getButlerByPlayerName(): Player with given name isn't active!"; return new Result(null, error); } String accountName = player.getAccountName(); synchronized(accnameToButler) { return new Result(accnameToButler.get(accountName), null); } } /** locks activePlayerNameToPlayer; mapnameToMapman */ public Result getMapmanByPlayerName(String playerName) { Player player = getActivePlayerByName(playerName); if (player == null) { String error = "getMapmanByPlayerName(): Player with given name isn't active!"; return new Result(null, error); } String mapName = player.getMapName(); synchronized(mapnameToMapman) { return new Result(mapnameToMapman.get(mapName), null); } } /** locks butlers
* Creates a butler who looks after the querying client at given socket. * That doesn't mean that the client is logged in already! */ public Butler createButler(Socket c){ Butler b = new Butler(this, c); synchronized(butlers) { butlers.add(b); } System.out.println("new butler for client at port "+c.getPort()); return b; } /** locks butlers */ public void deleteButler(Butler b){ synchronized(butlers) { assert(butlers.contains(b)); butlers.remove(b); } System.out.println("Butler at port " + b.getClientSocket().getPort()+" destroyed!"); } /** Creates a new account, but doesn't load it. */ public Result createAccount(String name, String password){ // TODO: Synchronise on file system? Or else two accounts could be // created under the same name, for example! // Check if an account already exists under given name: if (!existAccountSubdir(name)){ // account doesn't yet exist, create it (without players) Account acc = new Account(name, password, new ArrayList()); boolean createAccSuccess=createAccountSubdir(acc); if (createAccSuccess){ System.out.println("Account "+name+" successfully created."); return new Result(true, null); } else{ String error = "Account couldn't be created!?"; return new Result(null, error); } } else { String error = "Account name already exists!"; return new Result(null, error); } } /** locks accnameToButler, loggedAccnameToAccount
* logs out the account with the given name * Requirement: No more active players */ public Result logoutAccount(String accountName){ if (!loggedIn(accountName)){ String error = "This account isn't even logged in!"; return new Result(null, error); } // Check if there's still an active player: Account account; synchronized (loggedAccnameToAccount) { account = this.loggedAccnameToAccount.get(accountName); } Player activePlayer = account.getActivePlayer(); if (activePlayer != null) { String error = "Can't log out since there's still an active player!"; return new Result(null, error); } // log out: //saveAccount(acc); TODO synchronized(accnameToButler) { synchronized (loggedAccnameToAccount) { assert(loggedAccnameToAccount.containsKey(accountName)); assert(accnameToButler.containsKey(accountName)); loggedAccnameToAccount.remove(accountName); accnameToButler.remove(accountName); } } System.out.println("Account "+accountName+" successfully logged out."); return new Result(true, null); } /** locks loggedAccounts, accnameToButler */ public Result loginAccount(Butler butler, String name, String password){ // logs in the account with the given data if (!existAccountSubdir(name)){ String error = "Login to non-existent account failed!"; return new Result(null, error); } else if (loggedIn(name)){ String error = "This account is already logged in!";// TODO: Privacy?! return new Result(null, error); } else { // log in: Result result = loadAccount(name, password); if (result.successful()) { Account account = result.getResult(); synchronized(accnameToButler) { synchronized(loggedAccnameToAccount) { assert(!loggedAccnameToAccount.containsKey(name)); assert(!accnameToButler.containsKey(name)); loggedAccnameToAccount.put(name, account); accnameToButler.put(name, butler); } } System.out.println("Account "+name+" successfully logged in."); return new Result(account, null); } else { System.out.println("There were errors while logging in "+name+"."); return new Result(null, result.getErrorMessage()); } } } /** locks loggedAccounts
* Checks if an account of given name is already logged in. */ private boolean loggedIn(String name){ synchronized(loggedAccnameToAccount) { if (loggedAccnameToAccount.containsKey(name)) return true; return false; } } /** checks if a directory for given account name exists */ private boolean existAccountSubdir(String accountName){ File accountSubdir = new File(serverSettings.accountPath()+accountName+"/"); System.out.println("Check if "+accountSubdir.getPath()+" exists..."); return (accountSubdir.exists() && accountSubdir.isDirectory()); } /** Pure function.
* Loads an account from hard disk if exists and given login data is valid. * Additionally returns the loaded account if successful. */ private Result loadAccount(String name, String password){ if (!existAccountSubdir(name)){ String error = "Account "+name+" couldn't be loaded since it does not exist!"; return new Result(null, error); } String accountPath = serverSettings.accountPath(); // read account.txt: File accFile = new File(accountPath+name+"/account.txt"); BufferedReader reader; try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(accFile))); } catch (FileNotFoundException e) { System.out.println("Couldn't find account.txt for "+name); e.printStackTrace(); return new Result(null, "Error while reading account data!"); } String readPassword; try { readPassword = reader.readLine(); reader.close(); } catch (IOException e) { System.out.println("Error while reading account data!"); e.printStackTrace(); return new Result(null, "Error while reading account data!"); } // compare passwords if (!password.equals(readPassword)){ System.out.println("Password invalid, since "+password+" != "+readPassword); return new Result(null, "Invalid login data!"); } /* Login data valid, read further data: Read player names NOTE: The serialised player objects of the files in the directory "players" will only be loaded when a player is activated; Here we will just collect the player names. */ File accPlayerDir = new File(accountPath+name+"/players/"); File[] accPlayers = accPlayerDir.listFiles(); ArrayList playerNames = new ArrayList(); for (File p : accPlayers){ playerNames.add(p.getName()); } // Finally create the account object: Account acc = new Account(name, password, playerNames); System.out.println("Account "+name+" successfully loaded."); return new Result(acc, null); } /** locks allExistingPlayerNames, account, player
* Creates a new player on hard disk. You then still have to load it * by calling loadAndActivatePlayer().*/ public Result createNewPlayer(Account account, String playerName, CharacterClass type) { String starterRegion = serverSettings.starterRegion(); synchronized(allExistingPlayerNames) { synchronized(account) { Player player; String accountName = account.getName(); int maxPlayers = serverSettings.maxPlayersPerAccount(); ArrayList playerNames = account.getPlayerNames(); if (playerNames.size() >= maxPlayers) { String error = "You cannot exceed the limit of "+maxPlayers+" players per account!"; return new Result(null, error); } if (allExistingPlayerNames.contains(playerName)) { String error = "A player with the name "+playerName+" already exists!"; return new Result(null, error); } player = new Player(playerName, type, starterRegion, accountName); boolean success = savePlayer(player); if (success) { playerNames.add(playerName); allExistingPlayerNames.add(playerName); return new Result(true, null); } else { String error = "The player could not be created!"; return new Result(null, error); } } } } /** locks player
* Saves the current state of given player. */ public boolean savePlayer(Player player) { synchronized(player) { Path oldPath = player.getPath(); if (oldPath != null) System.out.println("WARNING: MainServer.savePlayer(): Player was still moving!"); // It's bad if there's still a path referenced in the given player object: // On no account may it be serialised with the player player.resetPath(); player.resetEmote(); String accountName = player.getAccountName(); String playerName = player.getName(); assert(existAccountSubdir(accountName)); String playerDirString = playerDirString(accountName, playerName); if (!existPlayerDir(accountName, playerName)) createPlayerDir(accountName, playerName); File playerFile = new File(playerDirString+"/"+playerName); FileOutputStream fos; ObjectOutputStream oos; try { fos = new FileOutputStream(playerFile); oos = new ObjectOutputStream(fos); oos.writeObject(player); oos.close(); } catch (IOException e) { e.printStackTrace(); player.setPath(oldPath); return false; } player.setPath(oldPath); } System.out.println("MainServer: Player successfully saved."); return true; } /** locks account, activePlayernameToPlayer
* Loads a player object from disk and returns it, or returns null if it failed. * => To be called by butlers!
* NOTE: The butler will yet have to assign the player to a mapman */ public Result loadAndActivatePlayer(Account account, String playerName) { if (account.getActivePlayer() != null) { String error = "Couldn't load "+playerName+" since there's still another player active!"; return new Result(null, error); } if (!account.getPlayerNames().contains(playerName)) { String error = "Couldn't load "+playerName+" since a player of that name doesn't exist!"; return new Result(null, error); } assert(this.existPlayerDir(account.getName(), playerName)); FileInputStream fis; ObjectInputStream ois; Player player = null; try { fis = new FileInputStream(playerDirString(account.getName(), playerName)+"/"+playerName); ois = new ObjectInputStream(fis); player = (Player) ois.readObject(); ois.close(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } assert(player != null); synchronized(account) { account.setActivePlayer(player); } synchronized(activePlayernameToPlayer) { activePlayernameToPlayer.put(playerName, player); } return new Result(player, null); } /** locks activePlayernameToPlayer, player, loggedAccnameToAccount, account
* => to be called by butlers!
* Saves and unloads given player.
* NOTE: Requires that given player is not registered at any mapmans * ( -> task of the butler to care about that)*/ public void unloadPlayer(Player player) { String accountName; synchronized(activePlayernameToPlayer) { synchronized(player) { this.savePlayer(player); accountName = player.getAccountName(); activePlayernameToPlayer.remove(player.getName()); } } Account account; synchronized(loggedAccnameToAccount) { account = loggedAccnameToAccount.get(accountName); } synchronized(account) { account.setActivePlayer(null); } } /** Creates the directory structure in the account directory for given account. * Returns true if successful, else false. */ private boolean createAccountSubdir(Account newAccount){ String accountPath = serverSettings.accountPath(); String newAccountName = newAccount.getName(); String newAccountPassword = newAccount.getPassword(); File newAccountDir = new File(accountPath+newAccountName+"/"); File newAccountPlayersDir = new File(accountPath+newAccountName+"/players"); File newAccountFile = new File(accountPath+newAccountName+"/account.txt"); boolean check = false; check = newAccountDir.mkdir(); check = check && newAccountPlayersDir.mkdir(); if (!check) return false; try { PrintWriter pw = new PrintWriter(newAccountFile); pw.println(newAccountPassword); pw.close(); } catch (IOException e) { e.printStackTrace(); return false; } return true; } private String playerDirString(String accountName, String playerName) { return serverSettings.accountPath()+accountName+"/players/"+playerName; } private boolean existPlayerDir(String accountName, String playerName){ File playerDir = new File(playerDirString(accountName, playerName)); return (playerDir.exists() && playerDir.isDirectory()); } private void createPlayerDir(String accountName, String playerName) { assert(!existPlayerDir(accountName, playerName)); File playerDir = new File(playerDirString(accountName, playerName)); playerDir.mkdir(); } /** NOTE: Doesn't wait until all threads have terminated. */ public void shutdownAll() { reception.shutdown(); synchronized(butlers) { for (Butler butler : butlers) { butler.put(new MBStopThreadOrder(null)); } } } private HashSet loadAllExistingPlayerNames() { HashSet result = new HashSet(); File accountDir = new File(serverSettings.accountPath()); File[] accounts = accountDir.listFiles(directoryFilter); for (File account : accounts) { File playersDir = new File(account.getPath()+"/players"); File[] players = playersDir.listFiles(directoryFilter); for (File player : players) { boolean added = result.add(player.getName()); if (!added) System.out.println("ERROR: Couldn't add "+player.getName()); } } return result; } } Faunis/src/server/Reception.java0000644000175000017500000000534212060472556015724 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** Exactly one instance is created. * Receives clients that want to connect to the game, * Creates butlers for them and redirects them to a new port. */ public class Reception{ protected boolean stopRunning; protected MainServer parent; private int port; // reception port where clients come to private Thread recThread; // runs in the background and listens at the port private Runnable recRunnable; // the job of recThread protected ServerSocket recSocket; // public Reception(MainServer parent, int port){ this.stopRunning = false; this.parent = parent; this.port = port; try { this.recSocket = new ServerSocket(this.port); } catch(Exception e) { e.printStackTrace(); System.out.println("Couldn't create reception socket!"); } this.recRunnable = new RecRunnable(); this.recThread = new Thread(this.recRunnable); this.recThread.start(); } class RecRunnable implements Runnable { public void run() { System.out.println("Reception runnable runs"); while(!stopRunning){ // Steadily listens at recSocket: // accept() blocks the execution until there's // an incoming client. // Negotiates a connection (clientSocket) with new clients // and creates a new butler for them. Socket clientSocket; try { clientSocket = recSocket.accept(); } catch (IOException e) { e.printStackTrace(); System.out.println("Error while listening to the reception socket!"); return; } System.out.println("Client heard, create butler ..."); parent.createButler(clientSocket); } } } /** NOTE: Execution doesn't wait for reception to terminate. */ public void shutdown() { stopRunning = true; try { recSocket.close(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("Couldn't choke reception thread!"); } } } Faunis/src/server/Account.java0000644000175000017500000000317412060472556015371 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server; import java.util.ArrayList; public class Account { private String name; private String password; private ArrayList playerNames; // Names of the players as they exist in // the directory "players" private Player activePlayer; // player which is currently loaded and controlled public Account(String name, String password, ArrayList playerNames){ this.name = name; this.password = password; this.playerNames = playerNames; this.activePlayer = null; } public String getName(){ return this.name; } public String getPassword(){ return this.password; } public ArrayList getPlayerNames() { return this.playerNames; } public Player getActivePlayer() { return this.activePlayer; } public void setActivePlayer(Player player) { this.activePlayer = player; } } Faunis/src/server/mapmanToButlerOrders/0000775000175000017500000000000012062730610017226 5ustar useruserFaunis/src/server/mapmanToButlerOrders/MBMapInfoOrder.java0000644000175000017500000000212312061574442022641 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.mapmanToButlerOrders; import server.MapManager; import communication.MapInfo; public class MBMapInfoOrder extends MBOrder { private MapInfo mapInfo; public MBMapInfoOrder(MapManager source, MapInfo mapInfo) { super(source); this.mapInfo = mapInfo; } public MapInfo getMapInfo() { return mapInfo; } } Faunis/src/server/mapmanToButlerOrders/MBOrder.java0000644000175000017500000000176612061574242021401 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.mapmanToButlerOrders; import server.MapManager; public abstract class MBOrder { private MapManager source; MBOrder(MapManager source) { this.source = source; } public MapManager getSource() { return source; } } Faunis/src/server/mapmanToButlerOrders/MBChatMessageOrder.java0000644000175000017500000000314712061574342023502 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.mapmanToButlerOrders; import server.MapManager; import server.butlerToMapmanOrders.BMChatMessageOrder; public class MBChatMessageOrder extends MBOrder { private String fromPlayername; private String toPlayername; private String message; public MBChatMessageOrder(MapManager source, String from, String to, String msg) { super(source); this.fromPlayername = from; this.toPlayername = to; this.message = msg; } public MBChatMessageOrder(MapManager source, BMChatMessageOrder order) { super(source); this.fromPlayername = order.getFromName(); this.toPlayername = order.getToName(); this.message = order.getMessage(); } public String getFromPlayername() { return fromPlayername; } public String getToPlayername() { return toPlayername; } public String getMessage() { return message; } } Faunis/src/server/mapmanToButlerOrders/MBErrorMessageOrder.java0000644000175000017500000000213112061574354023707 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.mapmanToButlerOrders; import server.MapManager; public class MBErrorMessageOrder extends MBOrder { private String errorMessage; public MBErrorMessageOrder(MapManager source, String errorMessage) { super(source); this.errorMessage = errorMessage; } public String getErrorMessage() { return errorMessage; } } Faunis/src/server/mapmanToButlerOrders/MBCharAtOtherMapmanOrder.java0000644000175000017500000000251512061574500024606 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.mapmanToButlerOrders; import server.MapManager; /** When the player steps on a link on the map, the MapManager tells the Butler * with this order that he should assign the player to a new MapManager. The * Butler has to do that on his own by calling unregister() and register(). */ public class MBCharAtOtherMapmanOrder extends MBOrder { private MapManager newMapman; public MBCharAtOtherMapmanOrder(MapManager source, MapManager newMapman) { super(source); this.newMapman = newMapman; } public MapManager getNewMapman() { return newMapman; } } Faunis/src/server/mapmanToButlerOrders/MBAddCharOrder.java0000644000175000017500000000301212061574274022577 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.mapmanToButlerOrders; import communication.GraphicalPlayerStatus; import server.MapManager; /** NOTE: The butler has to check if the source matches his registered * active map manager, or else it may be that a former MapManager still sends * events which don't belong to the new map anymore! */ public class MBAddCharOrder extends MBOrder { private String playerName; private GraphicalPlayerStatus graphStatus; public MBAddCharOrder(MapManager source, String playerName, GraphicalPlayerStatus graphStatus) { super(source); this.playerName = playerName; this.graphStatus = graphStatus; } public String getPlayerName() { return playerName; } public GraphicalPlayerStatus getGraphStatus() { return graphStatus; } } Faunis/src/server/mapmanToButlerOrders/MBChangeCharOrder.java0000644000175000017500000000256112061574306023300 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.mapmanToButlerOrders; import server.MapManager; import communication.GraphicalPlayerStatus; /** A character has changed its graphical status */ public class MBChangeCharOrder extends MBOrder { private String playerName; private GraphicalPlayerStatus graphStatus; public MBChangeCharOrder(MapManager source, String playerName, GraphicalPlayerStatus graphStatus) { super(source); this.playerName = playerName; this.graphStatus = graphStatus; } public String getPlayerName() { return playerName; } public GraphicalPlayerStatus getGraphStatus() { return graphStatus; } } Faunis/src/server/mapmanToButlerOrders/MBRemoveCharOrder.java0000644000175000017500000000211112061574324023337 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.mapmanToButlerOrders; import server.MapManager; public class MBRemoveCharOrder extends MBOrder { private String playerName; public MBRemoveCharOrder(MapManager source, String playerName) { super(source); this.playerName = playerName; } public String getPlayerName() { return playerName; } } Faunis/src/server/mapmanToButlerOrders/MBStopThreadOrder.java0000644000175000017500000000205012061574410023357 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.mapmanToButlerOrders; import server.MapManager; /** Used to stop the serverThread of a butler who is waiting to take orders * out of his BlockingQueue. */ public class MBStopThreadOrder extends MBOrder { public MBStopThreadOrder(MapManager source) { super(source); } } Faunis/src/server/Butler.java0000644000175000017500000004045012061600440015212 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.Socket; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import server.butlerToMapmanOrders.*; import server.mapmanToButlerOrders.*; import communication.butlerToClientOrders.*; import communication.clientToButlerOrders.*; import communication.enums.CharacterClass; import communication.enums.ClientStatus; /** The butler looks after the needs of a client. * He receives the socket that the reception has already created. * He represents his client on the server side. */ public class Butler { private Object shutdownMutexKey; private boolean shutdownOccupied; protected MainServer parent; private Socket clientSocket; // the socket through which to communicate with the client protected ObjectInputStream clientInput; // to read from the socket protected ObjectOutputStream clientOutput; // to write to the socket; synchronised access only private Thread clientThread; // steadily observes and handles the requests from the client private ClientRunnable clientRunnable; // the job of clientThread protected boolean stopRunning = false; // indicates termination to clientThread and serverThread protected Account loggedAccount; // Account, unter dem der Client gerade eingeloggt ist (kann auch null sein) protected Player activePlayer; protected MapManager activeMapman; protected BlockingQueue serverOrders; private Thread serverThread; // steadily observes and handles the requests from server side private ServerRunnable serverRunnable; // the job of serverThread public Butler(MainServer parent, Socket clientSocket){ this.shutdownMutexKey = new Object(); this.shutdownOccupied = false; this.parent = parent; this.clientSocket = clientSocket; this.serverOrders = new ArrayBlockingQueue(50); // create input and output streams from clientSocket System.out.println("Butler: Try to create input / output streams..."); try { this.clientOutput = new ObjectOutputStream(this.clientSocket.getOutputStream()); this.clientInput = new ObjectInputStream(this.clientSocket.getInputStream()); } catch (IOException e) { e.printStackTrace(); System.out.println("Couldn't create input / output stream!"); } System.out.println("Input and output streams have been created."); // create and start clientThread this.clientRunnable = new ClientRunnable(this); this.clientThread = new Thread(this.clientRunnable); this.clientThread.start(); // create and start serverThread this.serverRunnable = new ServerRunnable(this); this.serverThread = new Thread(this.serverRunnable); this.serverThread.start(); } public boolean assertActivePlayer() { if (activePlayer == null) { sendErrorMessage("Command requires loaded player!"); return false; } return true; } public boolean assertLoggedAccount() { if (loggedAccount == null) { sendErrorMessage("Command requires logged account!"); return false; } return true; } /** Shuts this butler down. Only one thread is allowed * to call this simultaneously. All others are rejected (returns false), * thus not blocked by calling this.
* This concurrency problem is solved by shutdownMutexKey * (the lock to synchronise on before shutdownOccupied is read), * and shutdownOccupied which indicates if the method is already * being called.
* Asserts that clientThread and serverThread terminate, * unless it isn't one of them that calls this method, in * which case only the termination of the other is asserted * and it is the responsibility of the caller to terminate afterwards * immediately. Thus, wherever clientThread / serverThread calls shutdown(), * it must terminate thereafter. */ public boolean shutdown(){ synchronized(shutdownMutexKey) { if (shutdownOccupied == true) return false; else shutdownOccupied = true; } System.out.println("Butler: Initiate shutdown..."); // Save data, log out, unregister butler etc. if (loggedAccount != null) logoutAccount(); parent.deleteButler(this); // Ask both threads of this butler to terminate: stopRunning = true; // Since both threads may be stuck waiting / listening, // we have to enforce termination! (:< // Enforce termination of serverThread by a special order: serverOrders.clear(); serverOrders.add(new MBStopThreadOrder(null)); // Enforce termination of clientThread by closing clientInput: try { clientInput.close(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("Couldn't choke clientThread!"); } if (Thread.currentThread() == this.clientThread) { // Only wait for serverThread to terminate: while (serverThread.isAlive()) {} } else if (Thread.currentThread() == this.serverThread) { // Only wait for clientThread to terminate: while (clientThread.isAlive()) {} } else { // wait for both threads to terminate: while (serverThread.isAlive() || clientThread.isAlive()) {} } shutdownOccupied = false; return true; } // ################################################################################# // Client -> Butler -> MapMan, Server side: // ################################################################################# public void loadActivePlayer(CBLoadPlayerOrder order) { if (!assertLoggedAccount()) return; else if (activePlayer != null) { sendErrorMessage("Butler: Couldn't load player: There's already one loaded."); return; } String playerName = order.getPlayerName(); Result query = parent.loadAndActivatePlayer(loggedAccount, playerName); if (!query.successful()) { sendErrorMessage(query.getErrorMessage()); return; } activePlayer = query.getResult(); // Assign player to mapman: String mapname = activePlayer.getMapName(); assert(mapname != null); assert(activeMapman == null); activeMapman = parent.getMapman(mapname); addPlayerToMapman(activeMapman, false); // => the mapman will send a MBMapInfoOrder // to the butler who passes it on to the client sendOrderToClient(new BCSetClientStatusOrder(ClientStatus.exploring)); System.out.println("Butler: Player "+playerName+" successfully loaded."); } /** Registers the active player at given mapman. * By doing so, the mapman will consequently send a MBMapInfoOrder * to the butler, who passes it on to the client.*/ private void addPlayerToMapman(MapManager mapman, boolean addPlayerMapEntry) { assert(activePlayer != null); assert(mapman != null); mapman.put(new BMRegisterOrder(this, activePlayer, addPlayerMapEntry)); } private void removePlayerFromMapman(MapManager mapman, boolean removePlayerMapEntry) { assert(activePlayer != null); assert(mapman != null); mapman.put(new BMUnregisterOrder(this, activePlayer, removePlayerMapEntry)); } public void unloadActivePlayer() { if (!assertLoggedAccount()) return; if (!assertActivePlayer()) return; assert(activeMapman != null); removePlayerFromMapman(activeMapman, false); parent.unloadPlayer(activePlayer); activePlayer = null; activeMapman = null; sendOrderToClient(new BCSetClientStatusOrder(ClientStatus.noCharLoaded)); System.out.println("Butler: Unloaded player."); } public void loginAccount(CBLoginOrder order) { if (loggedAccount == null) { Result query = parent.loginAccount(this, order.getName(), order.getPassword()); if (query.successful()) { loggedAccount = query.getResult(); sendOrderToClient(new BCSetClientStatusOrder(ClientStatus.noCharLoaded)); } else { sendErrorMessage(query.getErrorMessage()); } } else { sendErrorMessage("Butler: Couldn't log in since account seems to be already logged in."); } } public void logoutAccount() { if (loggedAccount != null) { if (activePlayer != null) { unloadActivePlayer(); } Result result = parent.logoutAccount(loggedAccount.getName()); if (!result.successful()) { sendErrorMessage(result.getErrorMessage()); return; } loggedAccount = null; sendOrderToClient(new BCSetClientStatusOrder(ClientStatus.loggedOut)); } else { sendErrorMessage("Butler: Couldn't log out since there's no account logged in!"); } } public void createNewPlayer(CBCreatePlayerOrder order) { if (!assertLoggedAccount()) return; Result result = parent.createNewPlayer(loggedAccount, order.getPlayerName(), CharacterClass.arctos); if (!result.successful()) sendErrorMessage(result.getErrorMessage()); } public void moveChar(CBMoveOrder order) { if (!assertLoggedAccount()) return; if (!assertActivePlayer()) return; activeMapman.put(new BMMoveOrder(activePlayer, this, order)); } /** friendly shutdown: Tells client that he's now disconnected */ public void disconnect() { sendOrderToClient(new BCSetClientStatusOrder(ClientStatus.disconnected)); if (!stopRunning) shutdown(); } public void forwardChatOrder(CBChatOrder order) { if (!assertActivePlayer()) return; activeMapman.put(new BMChatMessageOrder(this, order, activePlayer.getName())); } public void forwardEmoteOrder(CBTriggerEmoteOrder order) { if (!assertActivePlayer()) return; activeMapman.put(new BMTriggerEmoteOrder(this, activePlayer, order.getEmote())); } public Socket getClientSocket(){ return this.clientSocket; } // job of clientThread private class ClientRunnable implements Runnable { private Butler myButler; public ClientRunnable(Butler parent){ this.myButler = parent; } @Override public void run() { // Interpret client's requests: while(!stopRunning){ Object read = null; try { read = clientInput.readObject(); } catch(IOException e) { // Connection broken -> delete butler System.out.println("connection reset!!"); if (!stopRunning) //nobody ordered a shutdown, shutdown(); //so we will cause that on ourselves return; } catch(ClassNotFoundException e) { e.printStackTrace(); } if (read != null && read instanceof CBOrder){ // a clientOrder has been read: myButler.handleClientOrder((CBOrder) read); } } } } protected void handleClientOrder(CBOrder read) { if (read instanceof CBDisconnectOrder){ System.out.println("CBDisconnectOrder"); disconnect(); } else if (read instanceof CBCreatePlayerOrder) { System.out.println("CBCreatePlayerOrder"); createNewPlayer((CBCreatePlayerOrder) read); } else if (read instanceof CBChatOrder){ System.out.println("CBChatOrder"); forwardChatOrder((CBChatOrder) read); } else if (read instanceof CBLoginOrder){ System.out.println("CBLoginOrder"); loginAccount((CBLoginOrder) read); } else if (read instanceof CBLogoutOrder){ System.out.println("CBLogoutOrder"); logoutAccount(); } else if (read instanceof CBLoadPlayerOrder) { System.out.println("CBLoadPlayerOrder"); loadActivePlayer((CBLoadPlayerOrder) read); } else if (read instanceof CBUnloadPlayerOrder) { System.out.println("CBUnloadPlayerOrder"); unloadActivePlayer(); } else if (read instanceof CBMoveOrder) { System.out.println("CBMoveOrder"); moveChar((CBMoveOrder) read); } else if (read instanceof CBTriggerEmoteOrder) { System.out.println("CBTriggerEmoteOrder"); forwardEmoteOrder((CBTriggerEmoteOrder) read); } else if (read instanceof CBServerSourceOrder) { System.out.println("CBServerSourceOrder"); sendOrderToClient(new BCSystemMessageOrder( "Server source code at "+parent.getServerSettings().serverSourceAt())); } } // ################################################################################# // Mapman -> Butler -> Client side: // ################################################################################# public void put(MBOrder order) { try { serverOrders.put(order); } catch (InterruptedException e) { e.printStackTrace(); throw new RuntimeException("Couldn't pass server order to the butler!"); } } // job of serverThread private class ServerRunnable implements Runnable { private Butler myButler; public ServerRunnable(Butler parent) { this.myButler = parent; } @Override public void run() { // Handle queries lying in serverOrders MBOrder order; while (!stopRunning) { order = null; try { order = myButler.serverOrders.take(); } catch (InterruptedException e) { e.printStackTrace(); } if (order != null) myButler.handleServerOrder(order); } } } protected void handleServerOrder(MBOrder order) { // Assert that given order comes from our active mapman! // the only exception is if it's set to null (needed for chat orders, f.ex.) if (order.getSource() != null && order.getSource() != this.activeMapman) { System.out.println("Butler: Received order from foreign mapman!"); return; } if (order instanceof MBAddCharOrder) { clientAddChar((MBAddCharOrder) order); } else if (order instanceof MBChangeCharOrder) { clientChangeChar((MBChangeCharOrder) order); } else if (order instanceof MBRemoveCharOrder) { clientRemoveChar((MBRemoveCharOrder) order); } else if (order instanceof MBChatMessageOrder) { clientChatMessage((MBChatMessageOrder) order); } else if (order instanceof MBMapInfoOrder) { clientMapInfo((MBMapInfoOrder) order); } else if (order instanceof MBCharAtOtherMapmanOrder) { changeMapman((MBCharAtOtherMapmanOrder) order); } else if (order instanceof MBStopThreadOrder) { // If nobody else caused a shutdown, we will do if (!stopRunning) shutdown(); } else if (order instanceof MBErrorMessageOrder) { sendErrorMessage(((MBErrorMessageOrder) order).getErrorMessage()); } // TODO: Handle further serverside orders } /** locks clientOutput */ private void sendOrderToClient(BCOrder order) { assert(clientOutput != null); synchronized(clientOutput) { if (order == null) { System.out.println("Order is null!"); } try { clientOutput.writeObject(order); } catch (IOException e) { System.out.println("Butler: Couldn't pass order to client!"); } } } private void clientChatMessage(MBChatMessageOrder order) { String toName = order.getToPlayername(); boolean isBroadcast = (toName == null || toName.equals("")); sendOrderToClient(new BCChatMessageOrder(order.getMessage(), order.getFromPlayername(), isBroadcast)); } private void clientAddChar(MBAddCharOrder order) { sendOrderToClient(new BCAddCharOrder(order)); } private void clientChangeChar(MBChangeCharOrder order) { sendOrderToClient(new BCChangeCharOrder(order)); } private void clientRemoveChar(MBRemoveCharOrder order) { sendOrderToClient(new BCRemoveCharOrder(order)); } private void clientMapInfo(MBMapInfoOrder order) { sendOrderToClient(new BCSetMapOrder(order, activePlayer.getName())); } private void changeMapman(MBCharAtOtherMapmanOrder order) { MapManager oldMapman = order.getSource(); assert(this.activeMapman == oldMapman); MapManager newMapman = order.getNewMapman(); this.activeMapman = null; removePlayerFromMapman(oldMapman, true); addPlayerToMapman(newMapman, true); this.activeMapman = newMapman; } private void sendErrorMessage(String errorMessage) { sendOrderToClient(new BCErrorMessageOrder(errorMessage)); } } Faunis/src/server/butlerToMapmanOrders/0000775000175000017500000000000012062730610017226 5ustar useruserFaunis/src/server/butlerToMapmanOrders/BMUnregisterOrder.java0000644000175000017500000000241712061574172023445 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.butlerToMapmanOrders; import server.Butler; import server.Player; public class BMUnregisterOrder extends BMOrder { private Player player; private boolean removePlayerMapEntry; public BMUnregisterOrder(Butler source, Player player, boolean removePlayerMapEntry) { super(source); this.player = player; this.removePlayerMapEntry = removePlayerMapEntry; } public Player getPlayer() { return player; } public boolean getRemovePlayerMapEntry() { return removePlayerMapEntry; } } Faunis/src/server/butlerToMapmanOrders/BMOrder.java0000644000175000017500000000174612061574046021401 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.butlerToMapmanOrders; import server.Butler; public abstract class BMOrder { private Butler source; BMOrder(Butler source) { this.source = source; } public Butler getSource() { return source; } } Faunis/src/server/butlerToMapmanOrders/BMTriggerEmoteOrder.java0000644000175000017500000000221312061574120023676 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.butlerToMapmanOrders; import server.Butler; import server.Player; public class BMTriggerEmoteOrder extends BMOrder { private Player player; private String emote; public BMTriggerEmoteOrder(Butler source, Player player, String emote) { super(source); this.player = player; this.emote = emote; } public Player getPlayer() { return player; } public String getEmote() { return emote; } } Faunis/src/server/butlerToMapmanOrders/BMMoveOrder.java0000644000175000017500000000303612061574146022223 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.butlerToMapmanOrders; import communication.clientToButlerOrders.CBMoveOrder; import server.Butler; import server.Player; public class BMMoveOrder extends BMOrder { private Player player; private int xTarget; private int yTarget; public BMMoveOrder(Player player, Butler source, CBMoveOrder order) { super(source); this.player = player; this.xTarget = order.getXTarget(); this.yTarget = order.getYTarget(); } public BMMoveOrder(Player player, Butler source, int xTarget, int yTarget) { super(source); this.player = player; this.xTarget = xTarget; this.yTarget = yTarget; } public int getXTarget() { return xTarget; } public int getYTarget() { return yTarget; } public Player getPlayer() { return player; } } Faunis/src/server/butlerToMapmanOrders/BMRegisterOrder.java0000644000175000017500000000237112061574162023100 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.butlerToMapmanOrders; import server.Butler; import server.Player; public class BMRegisterOrder extends BMOrder { private Player player; private boolean addPlayerMapEntry; public BMRegisterOrder(Butler source, Player player, boolean addPlayerMapEntry) { super(source); this.player = player; this.addPlayerMapEntry = addPlayerMapEntry; } public Player getPlayer() { return player; } public boolean getAddPlayerMapEntry() { return addPlayerMapEntry; } } Faunis/src/server/butlerToMapmanOrders/BMChatMessageOrder.java0000644000175000017500000000330312061574130023467 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.butlerToMapmanOrders; import communication.clientToButlerOrders.CBChatOrder; import server.Butler; /** Represents a chat order which is forwarded from Butler to Mapman or * between Mapmans. Note that the corresponding Butler for toName is not yet * identified, therefore the forwarding. */ public class BMChatMessageOrder extends BMOrder { private String message; private String toName; private String fromName; public BMChatMessageOrder(Butler source, String message, String toName, String fromName) { super(source); this.message = message; this.toName = toName; this.fromName = fromName; } public BMChatMessageOrder(Butler source, CBChatOrder order, String fromName) { super(source); this.message = order.getMessage(); this.toName = order.getToName(); this.fromName = fromName; } public String getMessage() { return message; } public String getToName() { return toName; } public String getFromName() { return fromName; } } Faunis/src/server/butlerToMapmanOrders/BMMapInfoOrder.java0000644000175000017500000000165212061574456022654 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server.butlerToMapmanOrders; import server.Butler; public class BMMapInfoOrder extends BMOrder { public BMMapInfoOrder(Butler source) { super(source); } } Faunis/src/server/MapManager.java0000644000175000017500000003005512061600440015765 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server; import java.util.HashMap; import java.util.Set; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import client.AnimationData; import communication.GraphicalPlayerStatus; import communication.GraphicsContentManager; import communication.Map; import communication.MapInfo; import communication.enums.AniEndType; import communication.enums.CharacterClass; import communication.movement.Moveable; import communication.movement.Mover; import communication.movement.MoverManager; import communication.movement.MovingTask; import communication.movement.Path; import communication.movement.PathFactory; import communication.movement.RoughMovingTask; import server.butlerToMapmanOrders.*; import server.mapmanToButlerOrders.*; /** The map manager manages everything that happens on a map. There is exactly * one map manager for each map in the game. All players / butlers on a map have * to be registered at the map manager of that map. */ public class MapManager implements MoverManager { private MainServer parent; private Map map; private Thread thread; private Runnable runnable; protected BlockingQueue orders; private HashMap registeredPlayers; private HashMap playerNameToPlayer; private HashMap movingPlayers; public MapManager(MainServer parent, Map map) { this.parent = parent; this.map = map; this.registeredPlayers = new HashMap(); this.playerNameToPlayer = new HashMap(); this.movingPlayers = new HashMap(); orders = new ArrayBlockingQueue(50); runnable = new MapManRunnable(this); thread = new Thread(runnable); thread.start(); } private void tryStopMovement(Player player) { synchronized(movingPlayers) { synchronized(player) { Mover mover = movingPlayers.get(player); if (mover != null) { mover.stop(); unregisterMover(player); // TODO: I think we can sum the above to mover.stopAndUnregister(); } } } } public Object[] getSynchroStuffForMoverStop() { return new Object[] {movingPlayers}; } @Override public void unregisterMover(Moveable moveable) { assert(moveable instanceof Player); Player movingPlayer = (Player) moveable; synchronized(movingPlayers) { movingPlayers.remove(movingPlayer); } // TODO: Check if the player has landed on a link to another map } public void put(BMOrder order) { try { orders.put(order); } catch (InterruptedException e) { e.printStackTrace(); throw new RuntimeException("Couldn't pass the order to the mapman!"); } } public Map getMap() { return map; } public String getMapName() { return map.getName(); } protected void handleButlerOrder(BMOrder order) { assert(order != null); if (order instanceof BMMapInfoOrder) { MapInfo mapInfo = getMapInfo(); order.getSource().put(new MBMapInfoOrder(this, mapInfo)); } else if (order instanceof BMRegisterOrder) registerPlayer((BMRegisterOrder) order); else if (order instanceof BMUnregisterOrder) unregisterPlayer((BMUnregisterOrder) order); else if (order instanceof BMMoveOrder) movePlayer((BMMoveOrder) order); else if (order instanceof BMChatMessageOrder) bMChatMessageOrder((BMChatMessageOrder) order); else if (order instanceof BMTriggerEmoteOrder) bMTriggerEmoteOrder((BMTriggerEmoteOrder) order); // TODO Handle further orders } private void bMTriggerEmoteOrder(BMTriggerEmoteOrder order) { // TODO // determine if emote is valid for given player type: Player player = order.getPlayer(); CharacterClass type = player.getType(); String emote = order.getEmote(); if (emote == null || emote.equals("")) { // if an emote had been stored, delete it and notify all butlers deleteEmote(player); return; } GraphicsContentManager contentManager = parent.getGraphicsContentManager(); Set emotes = contentManager.getAvailableAnimations(type); if (!emotes.contains(emote)) { order.getSource().put(new MBErrorMessageOrder(this, "Emote is invalid!")); return; } // determine emote's AniEndType: AnimationData animationData = contentManager.getAnimationData(type, emote); assert(animationData != null); AniEndType endType = animationData.endType; if (endType != AniEndType.revert) { // store emote in player and notify all storeEmote(player, emote); } else { // fire and forget fireEmote(player, emote); } } /** locks registeredPlayers, player */ private void fireEmote(Player player, String emote) { synchronized(registeredPlayers) { synchronized(player) { GraphicalPlayerStatus status = player.getGraphicalPlayerStatus(); status.currentEmote = emote; notifyAllCharChanged(player.getName(), status); } } } /** locks registeredPlayers, player */ private void deleteEmote(Player player) { synchronized(registeredPlayers) { synchronized(player) { if (player.getCurrentEmote() != null) { player.setCurrentEmote(null); notifyAllCharChanged(player.getName(), player.getGraphicalPlayerStatus()); } } } } /** locks registeredPlayers, player */ private void storeEmote(Player player, String emote) { synchronized(registeredPlayers) { synchronized(player) { player.setCurrentEmote(emote); notifyAllCharChanged(player.getName(), player.getGraphicalPlayerStatus()); } } } /** locks registeredPlayers */ private void notifyAllCharChanged(String playerName, GraphicalPlayerStatus status) { synchronized(registeredPlayers ) { for (Butler butler : registeredPlayers.values()) { butler.put(new MBChangeCharOrder(this, playerName, status)); } } } private void bMChatMessageOrder(BMChatMessageOrder order) { System.out.println("Mapman forwards chat message"); String playerName = order.getToName(); if (playerName == null || playerName.equals("")) { // broadcast message to all players of this mapman synchronized(registeredPlayers) { for (Butler butler : registeredPlayers.values()) { butler.put(new MBChatMessageOrder(this, order)); } } return; } // else find the butler that corresponds to playerName Player player; synchronized(playerNameToPlayer) { player = playerNameToPlayer.get(playerName); } if (player != null) { Butler butler; synchronized(registeredPlayers ) { butler = registeredPlayers.get(player); } butler.put(new MBChatMessageOrder(this, order)); } else { Result butlerQuery = parent.getButlerByPlayerName(playerName); if (!butlerQuery.successful()) { String error = "Couldn't deliver message to given player."; order.getSource().put(new MBErrorMessageOrder(this, error)); return; } Butler butler = butlerQuery.getResult(); // Since the butler will only listen to his mapman, // we have to show him that it's okay by setting // the source to null: butler.put(new MBChatMessageOrder(null, order)); } } private void movePlayer(BMMoveOrder order) { assert(order != null); Player player = order.getPlayer(); synchronized (registeredPlayers) { assert(registeredPlayers.containsKey(player)); } // stop possible earlier movement: tryStopMovement(player); // stop possible earlier emote: deleteEmote(player); // if we are already at our target then return: if (order.getXTarget() == player.getX() && order.getYTarget() == player.getY()) return; String playerName; GraphicalPlayerStatus status; // build path and set its reference in the player object: synchronized(player) { Path path = PathFactory.createAirlinePath(player.getX(), player.getY(), order.getXTarget(), order.getYTarget()); player.setPath(path); playerName = player.getName(); status = player.getGraphicalPlayerStatus(); } // create new mover for player and add it: Mover mover; synchronized(movingPlayers) { mover = new Mover(this, player, 500); // TODO Zeiteinheit MovingTask movingTask = new RoughMovingTask(mover, player); mover.setMovingTask(movingTask); movingPlayers.put(player, mover); } // inform every registered butler about the change: synchronized(registeredPlayers) { notifyAllCharChanged(playerName, status); } mover.start(); // TODO } private void registerPlayer(BMRegisterOrder order) { assert(order != null); synchronized(registeredPlayers) { synchronized(playerNameToPlayer) { Player player = order.getPlayer(); String playername = player.getName(); Butler butler = order.getSource(); synchronized(player) { assert(!player.hasPath()); } assert(!playerNameToPlayer.containsKey(playername)); playerNameToPlayer.put(playername, player); assert(!registeredPlayers.containsKey(player)); registeredPlayers.put(player, butler); if (order.getAddPlayerMapEntry()) { synchronized(player) { assert(player.getMapName() == null); player.setMapName(this.map.getName()); } } // send map information to the new player's butler: MapInfo mapInfo = getMapInfo(); butler.put(new MBMapInfoOrder(this, mapInfo)); // send information about the new player to all other butlers: for (Butler butler2:registeredPlayers.values()) { if (butler2 != butler) butler2.put(new MBAddCharOrder(this, playername, player.getGraphicalPlayerStatus())); // TODO } } } } private void unregisterPlayer(BMUnregisterOrder order) { assert(order != null); synchronized(registeredPlayers) { synchronized(playerNameToPlayer) { Player player = order.getPlayer(); String playername = player.getName(); assert(playerNameToPlayer.containsKey(playername)); // stop possible earlier movement: tryStopMovement(player); // stop possible earlier emote: deleteEmote(player); playerNameToPlayer.remove(playername); assert(registeredPlayers.containsKey(player)); registeredPlayers.remove(player); if (order.getRemovePlayerMapEntry()) { synchronized(player) { assert(player.getMapName() != null); player.setMapName(null); } } // inform every registered butler about the leave: for (Butler butler2:registeredPlayers.values()) { butler2.put(new MBRemoveCharOrder(this, playername)); } } } } private MapInfo getMapInfo() { HashMap players = new HashMap(); synchronized(registeredPlayers) { for (Player player:registeredPlayers.keySet()) { GraphicalPlayerStatus graphStatus = player.getGraphicalPlayerStatus(); players.put(player.getName(), graphStatus); } } return new MapInfo(map.getName(), players); } private class MapManRunnable implements Runnable { private MapManager myMapman; public MapManRunnable(MapManager parent) { this.myMapman = parent; } @Override public void run() { BMOrder order; while (true) { order = null; try { order = myMapman.orders.take(); } catch (InterruptedException e) { e.printStackTrace(); } if (order != null) myMapman.handleButlerOrder(order); } } } } Faunis/src/server/ServerSettings.java0000644000175000017500000000526712061600730016755 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server; import java.io.File; public class ServerSettings { private String classPath; // paths are declared in constructor below; private String serverDataPath; // NOTE: All paths must end in "/" private String clientDataPath; private String accountPath; private String playerGraphicsPath; private String imageFileEnding = ".png"; private String starterRegion = "greenFields"; private int maxPlayersPerAccount = 3; private int receptionPort = 1024; private String serverSourceAt = "http://savannah.nongnu.org"; public ServerSettings() { try { classPath = getClass().getProtectionDomain(). getCodeSource().getLocation().toURI().getPath(); } catch (Exception e) { e.printStackTrace(); return; } //classPath = classPath.substring(1); // Windows error only? File classPathFile = new File(classPath); String parentPath = classPathFile.getParent()+"/"; serverDataPath = parentPath+"serverData/"; clientDataPath = parentPath+"clientData/"; accountPath = serverDataPath+"accounts/"; playerGraphicsPath = clientDataPath+"playerGraphics/"; } public String accountPath() { return accountPath; } public String starterRegion() { return starterRegion; } public String imageFileEnding() { return imageFileEnding; } public String playerGraphicsPath() { return playerGraphicsPath; } public int maxPlayersPerAccount() { return maxPlayersPerAccount; } public String serverSourceAt() { return serverSourceAt; } public int receptionPort() { return receptionPort; } public void checkPaths() { File accountDir = new File(accountPath); if (! (accountDir.exists() && accountDir.isDirectory())) System.out.println("WARNING: Account directory " +accountPath+"doesn't exist!"); File playerGraphicsDir = new File(accountPath); if (! (playerGraphicsDir.exists() && playerGraphicsDir.isDirectory())) System.out.println("WARNING: Player graphics directory " +playerGraphicsPath+" doesn't exist!"); } } Faunis/src/server/Result.java0000644000175000017500000000267112061600440015236 0ustar useruser/* Copyright 2012 Simon Ley alias "skarute" * * This file is part of Faunis. * * Faunis is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Faunis is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General * Public License along with Faunis. If not, see * . */ package server; /** Represents a result of the main server's methods when the method * may fail.
* The method execution was successful if errorMessage is null, * you will then find the requested object in the "requested" field. * If it failed, errorMessage contains a string with the reason. */ public class Result { private T result; private String errorMessage; public Result(T requested, String errorMessage) { this.result = requested; this.errorMessage = errorMessage; } public T getResult() { return result; } public String getErrorMessage() { return errorMessage; } public boolean successful() { return (errorMessage == null); } } Faunis/clientData/0000775000175000017500000000000012062730610013070 5ustar useruserFaunis/clientData/playerGraphics/0000775000175000017500000000000012062730610016045 5ustar useruserFaunis/clientData/playerGraphics/arctos/0000775000175000017500000000000012062730610017340 5ustar useruserFaunis/clientData/playerGraphics/arctos/stand/0000775000175000017500000000000012062730610020451 5ustar useruserFaunis/clientData/playerGraphics/arctos/stand/leftArm/0000775000175000017500000000000012062730610022043 5ustar useruserFaunis/clientData/playerGraphics/arctos/stand/leftArm/up.png0000644000175000017500000000134512062724432023203 0ustar useruserPNG  IHDR bOKbKGDԂ pHYsttfx vpAg ̽TIDAT(c`?Qʠ ͑ #!&†Wf!pB ӨFdk)2F*]g+0B9y-S-zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:52:54+01:00DIENDB`Faunis/clientData/playerGraphics/arctos/stand/leftArm/right.png0000644000175000017500000000133512062724432023673 0ustar useruserPNG  IHDR(վbKGDԂ pHYsttfx vpAgO~LIDATc`@G2200ɀ|3001!}Cl'ԊPPP w-F4(\)ԉzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:06:18+01:00/IENDB`Faunis/clientData/playerGraphics/arctos/stand/leftArm/down.png0000644000175000017500000000134412062724432023525 0ustar useruserPNG  IHDR rbKGDԂ pHYsttfx vpAg UfSIDAT8c`/?Z'`Bl`|HX5Er2mg u@FBk6 |'9q'B .SkzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T21:22:58+01:00KWIENDB`Faunis/clientData/playerGraphics/arctos/stand/leftArm/left.png0000644000175000017500000000133412062724432023507 0ustar useruserPNG  IHDR(վbKGDԂ pHYsttfx vpAgO~KIDATc`@G2200ɀ|3001!}C(k ڃHE&l^,)8zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:02:20+01:00Q:IENDB`Faunis/clientData/playerGraphics/arctos/stand/aniSettings.txt0000644000175000017500000000000712055502652023502 0ustar useruserrevert Faunis/clientData/playerGraphics/arctos/stand/leftLeg/0000775000175000017500000000000012062730610022033 5ustar useruserFaunis/clientData/playerGraphics/arctos/stand/leftLeg/up.png0000644000175000017500000000132312062724430023165 0ustar useruserPNG  IHDR /8bKGDԂ pHYsttfx vpAg L/A)BIDATc` ͑Pc(BQ94+ h@P#Gw #1 dzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:53:46+01:00}>~IENDB`Faunis/clientData/playerGraphics/arctos/stand/leftLeg/right.png0000644000175000017500000000134312062724430023660 0ustar useruserPNG  IHDR ,bKGDԂ pHYsttfx vpAg RIDATӝ Du"G >H0$%#Za֠Y fLJ.+`8ƈ=[3W۔zЉ:^0yzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:06:42+01:00JIENDB`Faunis/clientData/playerGraphics/arctos/stand/leftLeg/down.png0000644000175000017500000000136212062724430023513 0ustar useruserPNG  IHDRkIbKGDԂ pHYsttfx vpAgbaIDAT8c`V]`s$l }cWD I7ld$Ft L NCfs$א͑|6!D = @7pzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T21:22:18+01:00Y4IENDB`Faunis/clientData/playerGraphics/arctos/stand/leftLeg/left.png0000644000175000017500000000134212062724430023474 0ustar useruserPNG  IHDR ,bKGDԂ pHYsttfx vpAg QIDATӕ 1ѶR @6E9j$2qC>zPNdVNϣ3 3FzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:03:00+01:006pyIENDB`Faunis/clientData/playerGraphics/arctos/stand/rightLeg/0000775000175000017500000000000012062730610022216 5ustar useruserFaunis/clientData/playerGraphics/arctos/stand/rightLeg/up.png0000644000175000017500000000133112062724430023347 0ustar useruserPNG  IHDR \bKGDԂ pHYsttfx vpAg hHIDATcd``` .g`````d````BY΀0mġn&LYC$6#@ 02 'zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:54:54+01:004IENDB`Faunis/clientData/playerGraphics/arctos/stand/rightLeg/right.png0000644000175000017500000000134412062724430024044 0ustar useruserPNG  IHDR ,bKGDԂ pHYsttfx vpAg SIDATӝ D9_;:@_H,CrSTtVKA{5~ sp1m;~3 t3zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:07:32+01:00&MIENDB`Faunis/clientData/playerGraphics/arctos/stand/rightLeg/down.png0000644000175000017500000000135412062724430023677 0ustar useruserPNG  IHDRgbKGDԂ pHYsttfx vpAgw[IDAT8c`͑%|a5g9I3`K$A@3m.([3H& #I3+ ly? jzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T21:22:48+01:00VWPIENDB`Faunis/clientData/playerGraphics/arctos/stand/rightLeg/left.png0000644000175000017500000000134512062724430023662 0ustar useruserPNG  IHDR ,bKGDԂ pHYsttfx vpAg TIDATӝ 02aHK?b* ϖ cb:~6%`DI>PMPt2@g̡Ҏ}H>g7jV6FzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:03:38+01:009IENDB`Faunis/clientData/playerGraphics/arctos/stand/tail/0000775000175000017500000000000012060742046021406 5ustar useruserFaunis/clientData/playerGraphics/arctos/stand/body/0000775000175000017500000000000012062730610021406 5ustar useruserFaunis/clientData/playerGraphics/arctos/stand/body/up.png0000644000175000017500000000166512062724432022553 0ustar useruserPNG  IHDR"wgAMA asRGB cHRMz&u0`:pQ<bKGDԂ pHYsttfx vpAg" (lIDATHV[ \:O 9[ŏHx&-Q? e I 7z DcdEr`KHe«]Nu-9uIlMqT!56YBy읇t<ճLmUPȋst,EX_:nIX-gc*Q WH~{UH IC*@{e[X5<H:zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-03T21:13:16+01:00 5IENDB`Faunis/clientData/playerGraphics/arctos/stand/body/right.png0000644000175000017500000000144712062724430023240 0ustar useruserPNG  IHDRbKGDԂ pHYsttfx vpAg]âIDATHT XP!ܪ~`%EhKhA:pJb\{K/'݆qrXՕ.gaVSاis& L0kÚ9˳$3h P%?D8&K,zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-02T08:59:12+01:00$IENDB`Faunis/clientData/playerGraphics/arctos/stand/rightArm/0000775000175000017500000000000012062730610022226 5ustar useruserFaunis/clientData/playerGraphics/arctos/stand/rightArm/up.png0000644000175000017500000000134712062724430023366 0ustar useruserPNG  IHDRfBvbKGDԂ pHYsttfx vpAguOVIDAT(ϝ 0 C_tBP_K9D^鮟Z#(pGΐZk֮p9[ZgOq.7 zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:54:26+01:00Y^,IENDB`Faunis/clientData/playerGraphics/arctos/stand/rightArm/right.png0000644000175000017500000000133512062724430024054 0ustar useruserPNG  IHDR(վbKGDԂ pHYsttfx vpAgO~LIDATc`@#soddyž!rTj I}(?Qal(C#no%*WLzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:07:06+01:00\9IENDB`Faunis/clientData/playerGraphics/arctos/stand/rightArm/down.png0000644000175000017500000000135212062724430023705 0ustar useruserPNG  IHDR ЦŁbKGDԂ pHYsttfx vpAg *AYIDAT8c`?ҵ0`jb§as$HL |p\ch| -Ta$N%>aTlzX' ?/VL!zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T21:22:34+01:004=IENDB`Faunis/clientData/playerGraphics/arctos/stand/rightArm/left.png0000644000175000017500000000133412062724430023670 0ustar useruserPNG  IHDR(վbKGDԂ pHYsttfx vpAgO~KIDATc`@#soddyž!rى5PtBaxs$" @R 6/ *zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:03:56+01:00K'IENDB`Faunis/clientData/playerGraphics/arctos/stand/head/0000775000175000017500000000000012062730610021352 5ustar useruserFaunis/clientData/playerGraphics/arctos/stand/head/up.png0000644000175000017500000000135512062724430022511 0ustar useruserPNG  IHDR_bKGDԂ pHYsttfx vpAgW\IDAT8c`?$LjKHw9$,q|.Dq%.˰'eB>@766:\ TeÁ'F iYzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:44:14+01:00IENDB`Faunis/clientData/playerGraphics/arctos/stand/head/right.png0000644000175000017500000000142112062724430023174 0ustar useruserPNG  IHDRbKGDԂ pHYsttfx vpAgCAIDAT(ϝ 0E8:GG+ IB)@lҽ4Lpu6Sy,Tں!o6n; myh 15J/-AtēlN$b,%=&IzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:05:52+01:00sIENDB`Faunis/clientData/playerGraphics/arctos/stand/head/down.png0000644000175000017500000000161512062724430023033 0ustar useruserPNG  IHDR+vgAMA asRGB cHRMz&u0`:pQ<bKGDԂ pHYsttfx vpAg:IDAT8ݔ D类00Q$ $lcJSz=F_8ITvͅT-3h4 ZFl$nn9IҬk5Ğ|LfDǹ;*rx(,+(*o݁}ܽHֹW-k^bD~~~pZn'S|i(dzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-09-09T22:45:48+02:00"IENDB`Faunis/clientData/playerGraphics/arctos/stand/head/left.png0000644000175000017500000000141712062724430023016 0ustar useruserPNG  IHDRbKGDԂ pHYsttfx vpAgCA~IDAT(ϥ D@tP#jP;:M6=lc וzIKrP^ v}$oYk ( m$٥r|@͸D_V&> M 7zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:01:34+01:00HIENDB`Faunis/clientData/playerGraphics/arctos/walk/0000775000175000017500000000000012062730610020276 5ustar useruserFaunis/clientData/playerGraphics/arctos/walk/leftArm/0000775000175000017500000000000012062730610021670 5ustar useruserFaunis/clientData/playerGraphics/arctos/walk/leftArm/right3.png0000644000175000017500000000133512062724430023601 0ustar useruserPNG  IHDR(վbKGDԂ pHYsttfx vpAgO~LIDATc`@G2200ɀ|3001!}Cl'ԊPPP w-F4(\)ԉzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:33:54+01:00IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/left0.png0000644000175000017500000000141312062724430023410 0ustar useruserPNG  IHDRvbKGDԂ pHYsttfx vpAg-zIDAT8͓ g6 @cP!~0$Xu54,&T[1pfͮ/vGY6,Ćf430_U#b+Ԅef )JzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:30:08+01:00u5IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/left3.png0000644000175000017500000000133412062724430023415 0ustar useruserPNG  IHDR(վbKGDԂ pHYsttfx vpAgO~KIDATc`@G2200ɀ|3001!}C(k ڃHE&l^,)8zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:30:22+01:00mIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/left2.png0000644000175000017500000000142412062724430023414 0ustar useruserPNG  IHDRmJbKGDԂ pHYsttfx vpAgubIDAT8ݓ Dz :֟J =ChhyW [:亏=ô`d$GTE@r"v;T ^+DžԮx zfjl^b\hyچ)Ahއ:q QzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:29:56+01:00PôIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/up1.png0000644000175000017500000000134512062724430023107 0ustar useruserPNG  IHDR bOKbKGDԂ pHYsttfx vpAg ̽TIDAT(c`?Qʠ ͑ #!&†Wf!pB ӨFdk)2F*]g+0B9y-S-zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:52:54+01:00DIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/up2.png0000644000175000017500000000134412062724430023107 0ustar useruserPNG  IHDRfBvbKGDԂ pHYsttfx vpAguOSIDAT(c`πb&l#6GB8L 6r20,G"H X' )]( f_a>a"/zdzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T20:36:44+01:00IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/down2.png0000644000175000017500000000134512062724430023433 0ustar useruserPNG  IHDR ЦŁbKGDԂ pHYsttfx vpAg *ATIDAT8c`bdib ]`s$@ m|S`>ۨ'FBN$h6'R7I$md#Di,.zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T20:35:46+01:00OIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/up3.png0000644000175000017500000000134512062724430023111 0ustar useruserPNG  IHDR bOKbKGDԂ pHYsttfx vpAg ̽TIDAT(c`?Qʠ ͑ #!&†Wf!pB ӨFdk)2F*]g+0B9y-S-zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:52:54+01:00DIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/up0.png0000644000175000017500000000134512062724430023106 0ustar useruserPNG  IHDRfBvbKGDԂ pHYsttfx vpAguOTIDAT(c`πb&l#6GB8L 6rLr O)]fq$W`>a.N!+PezTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T20:36:54+01:00YIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/down3.png0000644000175000017500000000134412062724430023433 0ustar useruserPNG  IHDR rbKGDԂ pHYsttfx vpAg UfSIDAT8c`/?Z'`Bl`|HX5Er2mg u@FBk6 |'9q'B .SkzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T21:22:58+01:00KWIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/left1.png0000644000175000017500000000133412062724430023413 0ustar useruserPNG  IHDR(վbKGDԂ pHYsttfx vpAgO~KIDATc`@G2200ɀ|3001!}C(k ڃHE&l^,)8zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:29:38+01:00ƓJIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/right0.png0000644000175000017500000000142112062724430023572 0ustar useruserPNG  IHDRvbKGDԂ pHYsttfx vpAg-IDAT8͒ D(0^cey"WORp3yI;"#HP;$Md(H3&fV&.ixı()0j4֚t a)h];zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:33:48+01:00ZIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/right2.png0000644000175000017500000000141312062724430023575 0ustar useruserPNG  IHDRmJbKGDԂ pHYsttfx vpAgubzIDAT8c`X##}e"fe#H- E\k[Tq.|r2V\uA0000 hxg`n !zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:33:30+01:00#$IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/down1.png0000644000175000017500000000134412062724430023431 0ustar useruserPNG  IHDR rbKGDԂ pHYsttfx vpAg UfSIDAT8c`/?Z'`Bl`|HX5Er2mg u@FBk6 |'9q'B .SkzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T21:22:58+01:00KWIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/down0.png0000644000175000017500000000134712062724430023433 0ustar useruserPNG  IHDR ЦŁbKGDԂ pHYsttfx vpAg *AVIDAT8c`bdib ]`s$@ m|S`ٚp96P` ON"&|AV1O:.0zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T20:35:56+01:00jOsIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftArm/right1.png0000644000175000017500000000133512062724430023577 0ustar useruserPNG  IHDR(վbKGDԂ pHYsttfx vpAgO~LIDATc`@G2200ɀ|3001!}Cl'ԊPPP w-F4(\)ԉzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:33:40+01:00)=IENDB`Faunis/clientData/playerGraphics/arctos/walk/aniSettings.txt0000644000175000017500000000000712055507172023331 0ustar useruserrepeat Faunis/clientData/playerGraphics/arctos/walk/leftLeg/0000775000175000017500000000000012062730610021660 5ustar useruserFaunis/clientData/playerGraphics/arctos/walk/leftLeg/right3.png0000644000175000017500000000135112062724430023567 0ustar useruserPNG  IHDR kbKGDԂ pHYsttfx vpAg kVXIDAT(ϥ C9:(V$B[YEV\ODs !ʅ+4I>&nhpGxgzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:38:16+01:00IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/left0.png0000644000175000017500000000135412062724430023404 0ustar useruserPNG  IHDR obKGDԂ pHYsttfx vpAg 74[IDAT(ϝ L0}5[e*Dal >0r)H{WK"neѥ7o<:Y  -zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:37:40+01:00 nGIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/left3.png0000644000175000017500000000135212062724430023405 0ustar useruserPNG  IHDR kbKGDԂ pHYsttfx vpAg kVYIDAT(ϭ 0ݯd/h l8cш\j6}7Pd&ޠ:[nT'+={JzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:37:46+01:00C.[}IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/left2.png0000644000175000017500000000134312062724430023404 0ustar useruserPNG  IHDR kbKGDԂ pHYsttfx vpAg kVRIDAT(ϭ 0gR@*L)|E1hppbNz҂^6ȕ3 }6~T{*w1pzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:37:22+01:00qvIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/up1.png0000644000175000017500000000132312062724426023100 0ustar useruserPNG  IHDR /8bKGDԂ pHYsttfx vpAg L/A)BIDATc` ͑Pc(BQ94+ h@P#Gw #1 dzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:53:46+01:00}>~IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/up2.png0000644000175000017500000000132112062724430023072 0ustar useruserPNG  IHDR \bKGDԂ pHYsttfx vpAg h@IDATcd@#0rF&L 1md$*ŠMO"L"J#CEwfxP 9nzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T20:39:12+01:00&IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/down2.png0000644000175000017500000000135512062724430023424 0ustar useruserPNG  IHDRgbKGDԂ pHYsttfx vpAgw\IDAT8c`]`s$l }cWD oԩH&@N0{.I29,6Gb7#.G1T =4zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T20:38:24+01:00IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/up3.png0000644000175000017500000000132312062724430023075 0ustar useruserPNG  IHDR /8bKGDԂ pHYsttfx vpAg L/A)BIDATc` ͑Pc(BQ94+ h@P#Gw #1 dzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:53:46+01:00}>~IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/up0.png0000644000175000017500000000132712062724430023076 0ustar useruserPNG  IHDR \bKGDԂ pHYsttfx vpAg hFIDATӽA |av ,Rsa  %RWK${Tv =zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T20:39:20+01:006IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/down3.png0000644000175000017500000000136212062724430023423 0ustar useruserPNG  IHDRkIbKGDԂ pHYsttfx vpAgbaIDAT8c`V]`s$l }cWD I7ld$Ft L NCfs$א͑|6!D = @7pzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T21:22:18+01:00Y4IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/left1.png0000644000175000017500000000134212062724430023402 0ustar useruserPNG  IHDR ,bKGDԂ pHYsttfx vpAg QIDATӕ 1ѶR @6E9j$2qC>zPNdVNϣ3 3FzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:37:32+01:00vwIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/right0.png0000644000175000017500000000135312062724430023566 0ustar useruserPNG  IHDR obKGDԂ pHYsttfx vpAg 74ZIDAT(ϕ 0g#\a pyqhX!"6z1\TIS gYe4JLqlK|!67^rӣzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:38:10+01:00;IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/right2.png0000644000175000017500000000135012062724430023565 0ustar useruserPNG  IHDR kbKGDԂ pHYsttfx vpAg kVWIDAT(ϥ g_ @·$>X-Qp<'Ӽ$pA65V4š@7{Qu䢾7& }zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:37:54+01:00JIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/down1.png0000644000175000017500000000136212062724430023421 0ustar useruserPNG  IHDRkIbKGDԂ pHYsttfx vpAgbaIDAT8c`V]`s$l }cWD I7ld$Ft L NCfs$א͑|6!D = @7pzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T21:22:18+01:00Y4IENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/down0.png0000644000175000017500000000135312062724430023420 0ustar useruserPNG  IHDRgbKGDԂ pHYsttfx vpAgwZIDAT8c`]`s$l }cWD oԩH&$ U @H4׀͑C|c7$8O FAyzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T20:38:32+01:00WIENDB`Faunis/clientData/playerGraphics/arctos/walk/leftLeg/right1.png0000644000175000017500000000134312062724430023566 0ustar useruserPNG  IHDR ,bKGDԂ pHYsttfx vpAg RIDATӝ Du"G >H0$%#Za֠Y fLJ.+`8ƈ=[3W۔zЉ:^0yzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:38:04+01:00#IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightLeg/0000775000175000017500000000000012062730610022043 5ustar useruserFaunis/clientData/playerGraphics/arctos/walk/rightLeg/right3.png0000644000175000017500000000135712062724430023760 0ustar useruserPNG  IHDR kbKGDԂ pHYsttfx vpAg kV^IDAT(ϥ k`?mD$bwmWms1Jq<IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightLeg/left3.png0000644000175000017500000000134612062724430023573 0ustar useruserPNG  IHDR kbKGDԂ pHYsttfx vpAg kVUIDAT(ϭ /G _"PMPt2@g̡Ҏ}H>g7jV6FzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:36:14+01:00s/IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightLeg/right0.png0000644000175000017500000000135412062724430023752 0ustar useruserPNG  IHDR kbKGDԂ pHYsttfx vpAg kV[IDAT(ϕ 0WpKc  vgouOn޶.(^ ۙRI4es51w*FzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:26:18+01:00uIENDB`Faunis/clientData/playerGraphics/arctos/walk/rightLeg/right2.png0000644000175000017500000000135412062724430023754 0ustar useruserPNG  IHDR obKGDԂ pHYsttfx vpAg 74[IDAT(ϕ 0 |L`RZҊSD]gni%y^@aI[ɋaYJ̐4GZ3dzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:27:10+01:00IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightLeg/down1.png0000644000175000017500000000135412062724430023605 0ustar useruserPNG  IHDRgbKGDԂ pHYsttfx vpAgw[IDAT8c`͑%|a5g9I3`K$A@3m.([3H& #I3+ ly? jzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T21:22:48+01:00VWPIENDB`Faunis/clientData/playerGraphics/arctos/walk/rightLeg/down0.png0000644000175000017500000000135612062724430023606 0ustar useruserPNG  IHDRgbKGDԂ pHYsttfx vpAgw]IDAT8c`͑%|a5g9I3`K$A@0:l🁁9b:.0+e$]]QzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T20:20:16+01:00U IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightLeg/right1.png0000644000175000017500000000134412062724430023752 0ustar useruserPNG  IHDR ,bKGDԂ pHYsttfx vpAg SIDATӝ D9_;:@_H,CrSTtVKA{5~ sp1m;~3 t3zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:07:32+01:00&MIENDB`Faunis/clientData/playerGraphics/arctos/walk/tail/0000775000175000017500000000000012060742040021225 5ustar useruserFaunis/clientData/playerGraphics/arctos/walk/body/0000775000175000017500000000000012062730610021233 5ustar useruserFaunis/clientData/playerGraphics/arctos/walk/body/right3.png0000644000175000017500000000144712062724430023150 0ustar useruserPNG  IHDRbKGDԂ pHYsttfx vpAg]âIDATHT XP!ܪ~`%EhKhA:pJb\{K/'݆qrXՕ.gaVSاis& L0kÚ9˳$3h P%?D8&K,zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-02T08:59:12+01:00$IENDB`Faunis/clientData/playerGraphics/arctos/walk/body/left3.png0000644000175000017500000000145512062724430022764 0ustar useruserPNG  IHDR CbKGDԂ pHYsttfx vpAg IDATHQDGWp:~hP+ԇK,l(US Fn Gm5>{K/'݆qrXՕ.gaVSاis& L0kÚ9˳$3h P%?D8&K,zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-02T08:59:12+01:00$IENDB`Faunis/clientData/playerGraphics/arctos/walk/body/left2.png0000644000175000017500000000145512062724430022763 0ustar useruserPNG  IHDR CbKGDԂ pHYsttfx vpAg IDATHQDGWp:~hP+ԇK,l(US Fn Gm5>{K/'݆qrXՕ.gaVSاis& L0kÚ9˳$3h P%?D8&K,zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-02T08:59:12+01:00$IENDB`Faunis/clientData/playerGraphics/arctos/walk/body/up1.png0000644000175000017500000000166512062724430022457 0ustar useruserPNG  IHDR"wgAMA asRGB cHRMz&u0`:pQ<bKGDԂ pHYsttfx vpAg" (lIDATHV[ \:O 9[ŏHx&-Q? e I 7z DcdEr`KHe«]Nu-9uIlMqT!56YBy읇t<ճLmUPȋst,EX_:nIX-gc*Q WH~{UH IC*@{e[X5<H:zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-03T21:13:16+01:00 5IENDB`Faunis/clientData/playerGraphics/arctos/walk/body/up2.png0000644000175000017500000000166512062724430022460 0ustar useruserPNG  IHDR"wgAMA asRGB cHRMz&u0`:pQ<bKGDԂ pHYsttfx vpAg" (lIDATHV[ \:O 9[ŏHx&-Q? e I 7z DcdEr`KHe«]Nu-9uIlMqT!56YBy읇t<ճLmUPȋst,EX_:nIX-gc*Q WH~{UH IC*@{e[X5<H:zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-03T21:13:16+01:00 5IENDB`Faunis/clientData/playerGraphics/arctos/walk/body/down2.png0000644000175000017500000000146012062724430022774 0ustar useruserPNG  IHDR"wbKGDԂ pHYsttfx vpAg" (lIDATH!DƧaVE/fXZ]h)&5z͋ Hm)kK-Vgsvc,t'֒wuDáhX:S=rqNaK |EYׂ 8/z4Ab#PrzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-02T08:56:58+01:00IENDB`Faunis/clientData/playerGraphics/arctos/walk/body/up3.png0000644000175000017500000000166512062724430022461 0ustar useruserPNG  IHDR"wgAMA asRGB cHRMz&u0`:pQ<bKGDԂ pHYsttfx vpAg" (lIDATHV[ \:O 9[ŏHx&-Q? e I 7z DcdEr`KHe«]Nu-9uIlMqT!56YBy읇t<ճLmUPȋst,EX_:nIX-gc*Q WH~{UH IC*@{e[X5<H:zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-03T21:13:16+01:00 5IENDB`Faunis/clientData/playerGraphics/arctos/walk/body/up0.png0000644000175000017500000000166512062724430022456 0ustar useruserPNG  IHDR"wgAMA asRGB cHRMz&u0`:pQ<bKGDԂ pHYsttfx vpAg" (lIDATHV[ \:O 9[ŏHx&-Q? e I 7z DcdEr`KHe«]Nu-9uIlMqT!56YBy읇t<ճLmUPȋst,EX_:nIX-gc*Q WH~{UH IC*@{e[X5<H:zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-03T21:13:16+01:00 5IENDB`Faunis/clientData/playerGraphics/arctos/walk/body/down3.png0000644000175000017500000000146012062724430022775 0ustar useruserPNG  IHDR"wbKGDԂ pHYsttfx vpAg" (lIDATH!DƧaVE/fXZ]h)&5z͋ Hm)kK-Vgsvc,t'֒wuDáhX:S=rqNaK |EYׂ 8/z4Ab#PrzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-02T08:56:58+01:00IENDB`Faunis/clientData/playerGraphics/arctos/walk/body/left1.png0000644000175000017500000000145512062724430022762 0ustar useruserPNG  IHDR CbKGDԂ pHYsttfx vpAg IDATHQDGWp:~hP+ԇK,l(US Fn Gm5>{K/'݆qrXՕ.gaVSاis& L0kÚ9˳$3h P%?D8&K,zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-02T08:59:12+01:00$IENDB`Faunis/clientData/playerGraphics/arctos/walk/body/right0.png0000644000175000017500000000144712062724430023145 0ustar useruserPNG  IHDRbKGDԂ pHYsttfx vpAg]âIDATHT XP!ܪ~`%EhKhA:pJb\2aUdjLea[[[6Q2dNa,)+Z{H"%V5 :v# +Ydl#רJ"[ Fhx^!uj4ԝ\!V;2zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:32:12+01:00NIENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/left3.png0000644000175000017500000000133412062724430023600 0ustar useruserPNG  IHDR(վbKGDԂ pHYsttfx vpAgO~KIDATc`@#soddyž!rى5PtBaxs$" @R 6/ *zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:32:36+01:00™ IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/left2.png0000644000175000017500000000141012062724430023572 0ustar useruserPNG  IHDRvbKGDԂ pHYsttfx vpAg-wIDAT8͓A E\F$wLS%:Z=5{&TpDz=&-;XAQ&Yhͤj81EQ5"^J` 5a( [4zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:32:28+01:003WIENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/up1.png0000644000175000017500000000134712062724430023274 0ustar useruserPNG  IHDRfBvbKGDԂ pHYsttfx vpAguOVIDAT(ϝ 0 C_tBP_K9D^鮟Z#(pGΐZk֮p9[ZgOq.7 zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:54:26+01:00Y^,IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/up2.png0000644000175000017500000000135012062724430023267 0ustar useruserPNG  IHDRfBvbKGDԂ pHYsttfx vpAguOWIDAT(ϥ 0 C_tB@K9D^CP^=(G!Xyͷ * R[٤6W,A8GzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T20:34:06+01:00=*)IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/down2.png0000644000175000017500000000135312062724430023615 0ustar useruserPNG  IHDR ЦŁbKGDԂ pHYsttfx vpAg *AZIDAT8c`?ҵ0`jb§as$HL |p\ch|yxF _4 i"A'SORQ6 =F,j#1zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T20:28:54+01:00 *IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/up3.png0000644000175000017500000000134712062724430023276 0ustar useruserPNG  IHDRfBvbKGDԂ pHYsttfx vpAguOVIDAT(ϝ 0 C_tBP_K9D^鮟Z#(pGΐZk֮p9[ZgOq.7 zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:54:26+01:00Y^,IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/up0.png0000644000175000017500000000134712062724430023273 0ustar useruserPNG  IHDRfBvbKGDԂ pHYsttfx vpAguOVIDAT(ϝ D8iRJrؔ>eE&ۡ_bם$ ~MPV9g9G!,u(:0MzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T20:30:18+01:00XCIENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/down3.png0000644000175000017500000000135212062724430023615 0ustar useruserPNG  IHDR ЦŁbKGDԂ pHYsttfx vpAg *AYIDAT8c`?ҵ0`jb§as$HL |p\ch| -Ta$N%>aTlzX' ?/VL!zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T21:22:34+01:004=IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/left1.png0000644000175000017500000000133412062724430023576 0ustar useruserPNG  IHDR(վbKGDԂ pHYsttfx vpAgO~KIDATc`@#soddyž!rى5PtBaxs$" @R 6/ *zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:32:20+01:00IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/right0.png0000644000175000017500000000141012062724430023753 0ustar useruserPNG  IHDRmJbKGDԂ pHYsttfx vpAgubwIDAT8c`X##}e"feH,R"d Hq.`E(BaU\58!\ k0@]A5 ,x‚bA41DT(|zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:23:36+01:00-IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/right2.png0000644000175000017500000000141512062724430023762 0ustar useruserPNG  IHDRvbKGDԂ pHYsttfx vpAg-|IDAT8͒ D(0^ADftO|7o_Izv$/±is3Qz i+[qDҘifO5y8lkf˖HOY QH.S( zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-12-06T00:24:00+01:00 ~IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/down1.png0000644000175000017500000000135212062724430023613 0ustar useruserPNG  IHDR ЦŁbKGDԂ pHYsttfx vpAg *AYIDAT8c`?ҵ0`jb§as$HL |p\ch| -Ta$N%>aTlzX' ?/VL!zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T21:22:34+01:004=IENDB`Faunis/clientData/playerGraphics/arctos/walk/rightArm/down0.png0000644000175000017500000000135212062724430023612 0ustar useruserPNG  IHDR ЦŁbKGDԂ pHYsttfx vpAg *AYIDAT8c`?ҵ0`jb§as$HL |p\ch| -T i"48,MPQ6 =F,j`V- M 7zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:01:34+01:00HIENDB`Faunis/clientData/playerGraphics/arctos/walk/head/left3.png0000644000175000017500000000141712062724430022726 0ustar useruserPNG  IHDRbKGDԂ pHYsttfx vpAgCA~IDAT(ϥ D@tP#jP;:M6=lc וzIKrP^ v}$oYk ( m$٥r|@͸D_V&> M 7zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:01:34+01:00HIENDB`Faunis/clientData/playerGraphics/arctos/walk/head/left2.png0000644000175000017500000000141712062724430022725 0ustar useruserPNG  IHDRbKGDԂ pHYsttfx vpAgCA~IDAT(ϥ D@tP#jP;:M6=lc וzIKrP^ v}$oYk ( m$٥r|@͸D_V&> M 7zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:01:34+01:00HIENDB`Faunis/clientData/playerGraphics/arctos/walk/head/up1.png0000644000175000017500000000135512062724430022417 0ustar useruserPNG  IHDR_bKGDԂ pHYsttfx vpAgW\IDAT8c`?$LjKHw9$,q|.Dq%.˰'eB>@766:\ TeÁ'F iYzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:44:14+01:00IENDB`Faunis/clientData/playerGraphics/arctos/walk/head/up2.png0000644000175000017500000000135512062724430022420 0ustar useruserPNG  IHDR_bKGDԂ pHYsttfx vpAgW\IDAT8c`?$LjKHw9$,q|.Dq%.˰'eB>@766:\ TeÁ'F iYzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:44:14+01:00IENDB`Faunis/clientData/playerGraphics/arctos/walk/head/down2.png0000644000175000017500000000161512062724430022742 0ustar useruserPNG  IHDR+vgAMA asRGB cHRMz&u0`:pQ<bKGDԂ pHYsttfx vpAg:IDAT8ݔ D类00Q$ $lcJSz=F_8ITvͅT-3h4 ZFl$nn9IҬk5Ğ|LfDǹ;*rx(,+(*o݁}ܽHֹW-k^bD~~~pZn'S|i(dzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-09-09T22:45:48+02:00"IENDB`Faunis/clientData/playerGraphics/arctos/walk/head/up3.png0000644000175000017500000000135512062724430022421 0ustar useruserPNG  IHDR_bKGDԂ pHYsttfx vpAgW\IDAT8c`?$LjKHw9$,q|.Dq%.˰'eB>@766:\ TeÁ'F iYzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:44:14+01:00IENDB`Faunis/clientData/playerGraphics/arctos/walk/head/up0.png0000644000175000017500000000135512062724430022416 0ustar useruserPNG  IHDR_bKGDԂ pHYsttfx vpAgW\IDAT8c`?$LjKHw9$,q|.Dq%.˰'eB>@766:\ TeÁ'F iYzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T22:44:14+01:00IENDB`Faunis/clientData/playerGraphics/arctos/walk/head/down3.png0000644000175000017500000000161512062724430022743 0ustar useruserPNG  IHDR+vgAMA asRGB cHRMz&u0`:pQ<bKGDԂ pHYsttfx vpAg:IDAT8ݔ D类00Q$ $lcJSz=F_8ITvͅT-3h4 ZFl$nn9IҬk5Ğ|LfDǹ;*rx(,+(*o݁}ܽHֹW-k^bD~~~pZn'S|i(dzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-09-09T22:45:48+02:00"IENDB`Faunis/clientData/playerGraphics/arctos/walk/head/left1.png0000644000175000017500000000141712062724430022724 0ustar useruserPNG  IHDRbKGDԂ pHYsttfx vpAgCA~IDAT(ϥ D@tP#jP;:M6=lc וzIKrP^ v}$oYk ( m$٥r|@͸D_V&> M 7zTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:01:34+01:00HIENDB`Faunis/clientData/playerGraphics/arctos/walk/head/right0.png0000644000175000017500000000142112062724430023101 0ustar useruserPNG  IHDRbKGDԂ pHYsttfx vpAgCAIDAT(ϝ 0E8:GG+ IB)@lҽ4Lpu6Sy,Tں!o6n; myh 15J/-AtēlN$b,%=&IzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:05:52+01:00sIENDB`Faunis/clientData/playerGraphics/arctos/walk/head/right2.png0000644000175000017500000000142112062724430023103 0ustar useruserPNG  IHDRbKGDԂ pHYsttfx vpAgCAIDAT(ϝ 0E8:GG+ IB)@lҽ4Lpu6Sy,Tں!o6n; myh 15J/-AtēlN$b,%=&IzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:05:52+01:00sIENDB`Faunis/clientData/playerGraphics/arctos/walk/head/down1.png0000644000175000017500000000161512062724430022741 0ustar useruserPNG  IHDR+vgAMA asRGB cHRMz&u0`:pQ<bKGDԂ pHYsttfx vpAg:IDAT8ݔ D类00Q$ $lcJSz=F_8ITvͅT-3h4 ZFl$nn9IҬk5Ğ|LfDǹ;*rx(,+(*o݁}ܽHֹW-k^bD~~~pZn'S|i(dzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-09-09T22:45:48+02:00"IENDB`Faunis/clientData/playerGraphics/arctos/walk/head/down0.png0000644000175000017500000000161512062724430022740 0ustar useruserPNG  IHDR+vgAMA asRGB cHRMz&u0`:pQ<bKGDԂ pHYsttfx vpAg:IDAT8ݔ D类00Q$ $lcJSz=F_8ITvͅT-3h4 ZFl$nn9IҬk5Ğ|LfDǹ;*rx(,+(*o݁}ܽHֹW-k^bD~~~pZn'S|i(dzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-09-09T22:45:48+02:00"IENDB`Faunis/clientData/playerGraphics/arctos/walk/head/right1.png0000644000175000017500000000142112062724430023102 0ustar useruserPNG  IHDRbKGDԂ pHYsttfx vpAgCAIDAT(ϝ 0E8:GG+ IB)@lҽ4Lpu6Sy,Tں!o6n; myh 15J/-AtēlN$b,%=&IzTXtcommentxڅRMk@rjmzKKA5v"pm#[}b}i-2|-e_{| Mm]eSQ388cI!k["1/8mLRpzΚT $\g7VSzRfz9JGl3L 8{qNDhZJ쭲SRfqF= b ďqB+[e VNɕ03xݡC=jjbdRthSQ'3?WvՏzSwGHºzנ¾jzyT fkWsDPOu:IJ"Cs쥄7aqaz*TA#}j(:C&2߼X82tYj^|z|%tEXtdate:create2012-12-14T22:19:50+01:00Z%tEXtdate:modify2012-11-01T23:05:52+01:00sIENDB`Faunis/clientData/playerGraphics/arctos/sketch.png0000644000175000017500000001257412062724426021346 0ustar useruserPNG  IHDR bKGDԂ pHYsttfx vpAg >qIDATxMh\UǟӆvlbiEMqd'tӅ.)} Ņ]E'-h](iAꢐnb$hwə;{!ssff 666 @ D"hH@$Z]1BPwEDԬeBTc7f<7>ܘf掿 >nH1(7F$T/S 4;JnDVIA@/EBzR4>FI$Y GD(@|df'0>& Dݥ< NZFwv YV9Vqi[j66~D"\=z̧P3ⷍD)wQ&Ҷd66~DB2Hyxj+llF@C aXvK=loSWʓH.W'"9,}W<_vff/+vCǕmm2Jek;u66~e,WmgllQhvM_FVHB NuMf+lhmnIJ\=T;C#T{\f;EүHIJ\=4;PV66}}i!ڑ,WigI{\Id+ldNpI;7Q).=${\f;ߦY$ "Qm3 "3^CB[#;|N Wη{'dii'B(vHD]ID?w5L)UgK۲xYKPֆ@*B#yeg C}u1-[DD$xUk3Om6/iL'vbL/\Q|yHqrTL|'m'*~%@C%15=ل-& ͞mY:4i;i#heH8 k~5Sd)MLKH& 5;l^#BsC'i[&ljHzY湸9&G^uC$R) H3pl]HXĆ[ӽ],iB"̥p&g;b&BÓ⫩_#z`3EՓHyxzbGe.~Un3#s O^|UX|uv5Pr6{KIOI擴PYrGU:%.~V=wVZ$@6RCbtx'k&ll6ltP"$Nu=7Y)y{(ϛg^"OtHȂ) (,27{()=YBA;oiF/iiR qu:N#Sتv%1_iAtP,%~ױi6q^+ކe=jrkLehO$lMh A"R> 9 - @ D"hH`89>Csr?!B$蒩ia6,47AvSԴ@$(X"]'_k#]D!  x@$ M"wнMn4/"4pM`2GU<ݱ*_RȾCd:!eӠ^Lza*zBv ?%e}Pb^BG$| u@:k=UD ބ4uOlQM B S5e3DEA(%_7MkK0'\ uôFqnj^c:Ofs3[u$xvSƚX꜍`EB T ALQT@ > ltz :E44oId1S_ feQ >,  rTPwSs>OH]1'QQO9+='QQעB#ON)f?5765$N1bm4SS/Q<ɩīџ Gf+icC"nU|?pOVD|ܾ$@T@HT2QDbMR$x"%M-|_)USw|X;O[" %F@K"A*!j< c > $#'?WM(=]4!u1949pL/s@N2gH K^[9V+zN5kToi(h2ڥ ER8Bvuy,ByHx :˔O!ޛE( ZN5O]#k.hnEV+yS@_b|Q ɠ!mh|`!]^P! *DFH`*H(,H`сH`*65 E L ,WP8H XP8""-XqQpLjY}ϙ|OxjJ`ߋI ǐ"cBY^@ D$w=2 DT!Dͥ;fۦ"33gHB =˴K=/ -xގA᲏Q%>͆P;Mm%& K{`S hBկHDqI`2bpn&d\hhH@$Z  jpPAc"P@ Q#ٰyՁHhBedkh։H`[0DI[Qx- &6@$@t~>p1Qa‹} ŀHh![Hh0a~H@$@_~| - %jcz'JTʫM,h_ީT.^h$-֭[tYzgF"68$i /͛Gyn6ڿ?ODDo8 O.\ "7L###tw驧477O;wANk/3_Ew*e>FFFht4ڼYѓ^O;gZ9-Y.Yڱc-//ˎ;hvv._LcccTh߾}tҥ[/ijM6z3?N7n^{g[/qff~'رc9?Wy~~Ϝ9zזΑ0_xonBDmロ^MW{``_yӧO޽{esc:Wg3YYy˺̇3g03ӧСC<11o/..oH=_7/k x)!"7n]-[03sV7o"33]4~m_|ϝ;+++Kѣ<11MWaaam%|J=^wNe'|Gaf#Gp`f桡!gf?S:1H;Q/Ag;o۶~wںuk?!Yi]v:uٳ?M~~NZXXL7͆$/ڵ}ٶ￴ay&mݺ9yy˲A6.]D{+W͛i۶mtU7n]wEsssNw.J,LPFw 'эG}?Nҁ'N<}4::MgӦM4;;Msll{z_'Oj\ZZw}ݫM=JsO@ ۹shqqN8A]3+oj _V_>%zwhllwFć Faunis/README.txt0000644000175000017500000000503212062725730012523 0ustar useruserCopyright 2012 Simon Ley alias "skarute" This documentation is published under the GNU Free Documentation License v1.3 or later. You can find a copy of this license in "fdl-1.3.txt" or at . ######################################## Faunis 0.1 - a free furry MMORPG ######################################## All files of Faunis are copyrighted: Copyright 2012 Simon Ley alias "skarute" All files of Faunis are licensed under the GNU AGPL v3 or later, except for the documentation files "README.txt", "devdoc.txt" and "windows.txt", which are licensed under the GNU FDL v1.3 or later. Faunis is still under heavy development, so don't expect too much for now. :o] 1. Requirements To execute: Java Runtime Environment (JRE) 6 or higher. To compile: Java Development Kit (JDK) 6 or higher. Optionally eclipse as IDE. Windows users may find some tips in the included file "windows.txt". 2. How to compile Faunis is developed in eclipse. If you want to use this IDE, you can just import the whole Faunis directory. If not, you may use the Makefile, the target "clean" removes all compiled data, the target "compile" rebuilds server and client. Also note that Faunis is delivered precompiled, so you don't need to compile if you don't want to. 3. How to play The command to run the client is defined under the "runClient" target in the Makefile, whilst the command to start the server is under "runServer". 4. Quick introduction into the client usage The client status is shown in the left upper corner. It can be "disconnected", "logged out", "no character loaded" or "exploring". Currently the client doesn't support any mouse commands, so to actually do something, you have to type commands into the field at the bottom. There are the following commands: To connect to the server, type: /c Log in: /i username password Load player: /l playername Walk around: /m xcoordinate ycoordinate Send private message: /w username message Broadcast message: /b message Request server source code: /s Create new player: /n playername Trigger emote: /e emote Unload player: /u Log out: /o Disconnect: /x Note that in the default configuration, the server is contacted at localhost, so you have to start a server instance on the same machine to be able to connect. 5. Server usage Just start it and it should do the rest. Is also configured to use localhost. Close the window when you have enough. 6. Configurating client and server Client and server settings are until now hardcoded. To change them, edit the ClientSettings and ServerSettings classes and recompile. Faunis/bin/0000775000175000017500000000000012063430423011570 5ustar useruserFaunis/bin/communication/0000775000175000017500000000000012063430423014435 5ustar useruserFaunis/bin/communication/GraphicalPlayerStatus.class0000664000175000017500000000137012063430423021740 0ustar useruser2( " # $%&'serialVersionUIDJ ConstantValuenameLjava/lang/String;type$Lcommunication/enums/CharacterClass;xIy directionLcommunication/enums/Direction;pathLcommunication/movement/Path; currentEmote()VCodeLineNumberTablehasPath()Z StackMapTablehasEmote SourceFileGraphicalPlayerStatus.java    #communication/GraphicalPlayerStatusjava/lang/Objectjava/io/Serializable!    & ** %0 *) @0 *- @ !Faunis/bin/communication/Map.class0000664000175000017500000000104112063430423016175 0ustar useruser2    nameLjava/lang/String;widthIheight(Ljava/lang/String;II)VCodeLineNumberTablegetName()Ljava/lang/String;getWidth()I getHeight SourceFileMap.java   communication/Mapjava/lang/Object()V!   <**+** *!*%*)Faunis/bin/communication/butlerToClientOrders/0000775000175000017500000000000012063430422020552 5ustar useruserFaunis/bin/communication/butlerToClientOrders/BCChatMessageOrder.class0000664000175000017500000000130412063430422025164 0ustar useruser2"     serialVersionUIDJ ConstantValuemessageLjava/lang/String;fromName isBroadcastZ((Ljava/lang/String;Ljava/lang/String;Z)VCodeLineNumberTable getMessage()Ljava/lang/String; getFromName()Z SourceFileBCChatMessageOrder.java !  5communication/butlerToClientOrders/BCChatMessageOrder*communication/butlerToClientOrders/BCOrder()V!    <**+*,*  *#*'*+Faunis/bin/communication/butlerToClientOrders/BCAddCharOrder.class0000664000175000017500000000141512063430422024271 0ustar useruser2%      !"serialVersionUIDJ ConstantValue playerNameLjava/lang/String; graphStatus%Lcommunication/GraphicalPlayerStatus;/(Lserver/mapmanToButlerOrders/MBAddCharOrder;)VCodeLineNumberTable getPlayerName()Ljava/lang/String;getGraphStatus'()Lcommunication/GraphicalPlayerStatus; SourceFileBCAddCharOrder.java #$    1communication/butlerToClientOrders/BCAddCharOrder*communication/butlerToClientOrders/BCOrder()V*server/mapmanToButlerOrders/MBAddCharOrder!    9**+*+ !"*%*)Faunis/bin/communication/butlerToClientOrders/BCSetClientStatusOrder.class0000664000175000017500000000106012063430422026075 0ustar useruser2  serialVersionUIDJ ConstantValue newStatus"Lcommunication/enums/ClientStatus;%(Lcommunication/enums/ClientStatus;)VCodeLineNumberTable getNewStatus$()Lcommunication/enums/ClientStatus; SourceFileBCSetClientStatusOrder.java  9communication/butlerToClientOrders/BCSetClientStatusOrder*communication/butlerToClientOrders/BCOrder()V!  * **+ *!Faunis/bin/communication/butlerToClientOrders/BCChangeCharOrder.class0000664000175000017500000000143112063430422024764 0ustar useruser2%      !"serialVersionUIDJ ConstantValue playerNameLjava/lang/String; graphStatus%Lcommunication/GraphicalPlayerStatus;2(Lserver/mapmanToButlerOrders/MBChangeCharOrder;)VCodeLineNumberTable getPlayerName()Ljava/lang/String;getGraphStatus'()Lcommunication/GraphicalPlayerStatus; SourceFileBCChangeCharOrder.java #$    4communication/butlerToClientOrders/BCChangeCharOrder*communication/butlerToClientOrders/BCOrder()V-server/mapmanToButlerOrders/MBChangeCharOrder!    9**+*+ ! "#*&**Faunis/bin/communication/butlerToClientOrders/BCOrder.class0000664000175000017500000000047312063430422023065 0ustar useruser2 serialVersionUIDJ ConstantValue()VCodeLineNumberTable SourceFile BCOrder.java *communication/butlerToClientOrders/BCOrderjava/lang/Objectjava/io/Serializable!  * Faunis/bin/communication/butlerToClientOrders/BCSystemMessageOrder.class0000664000175000017500000000077012063430422025577 0ustar useruser2  serialVersionUIDJ ConstantValuemessageLjava/lang/String;(Ljava/lang/String;)VCodeLineNumberTable getMessage()Ljava/lang/String; SourceFileBCSystemMessageOrder.java  7communication/butlerToClientOrders/BCSystemMessageOrder*communication/butlerToClientOrders/BCOrder()V!  * **+ *Faunis/bin/communication/butlerToClientOrders/BCErrorMessageOrder.class0000664000175000017500000000076612063430422025411 0ustar useruser2  serialVersionUIDJ ConstantValuemessageLjava/lang/String;(Ljava/lang/String;)VCodeLineNumberTable getMessage()Ljava/lang/String; SourceFileBCErrorMessageOrder.java  6communication/butlerToClientOrders/BCErrorMessageOrder*communication/butlerToClientOrders/BCOrder()V!  * **+ *Faunis/bin/communication/butlerToClientOrders/BCSetMapOrder.class0000664000175000017500000000137012063430422024174 0ustar useruser2#     serialVersionUIDJ ConstantValuemapInfoLcommunication/MapInfo;activePlayerNameLjava/lang/String;A(Lserver/mapmanToButlerOrders/MBMapInfoOrder;Ljava/lang/String;)VCodeLineNumberTable getMapInfo()Lcommunication/MapInfo;getActivePlayerName()Ljava/lang/String; SourceFileBCSetMapOrder.java !"  0communication/butlerToClientOrders/BCSetMapOrder*communication/butlerToClientOrders/BCOrder()V*server/mapmanToButlerOrders/MBMapInfoOrder!   6**+*, ! "#*&**Faunis/bin/communication/butlerToClientOrders/BCRemoveCharOrder.class0000664000175000017500000000112512063430422025034 0ustar useruser2   serialVersionUIDJ ConstantValue playerNameLjava/lang/String;2(Lserver/mapmanToButlerOrders/MBRemoveCharOrder;)VCodeLineNumberTable getPlayerName()Ljava/lang/String; SourceFileBCRemoveCharOrder.java   4communication/butlerToClientOrders/BCRemoveCharOrder*communication/butlerToClientOrders/BCOrder()V-server/mapmanToButlerOrders/MBRemoveCharOrder!   - **+ *"Faunis/bin/communication/GraphicsContentManager.class0000664000175000017500000002377612063430422022070 0ustar useruser2 s q q  q >  q q q q q q q q q q          N   q   q      > > > > > >           q    q  >   U q U!"#$% q&' `()* d+ c, b- b. b/01234 56 78 9:; graphicsPathLjava/lang/String; fileEndingbonesLjava/util/HashMap; SignatureLjava/util/HashMap;>;>;>; drawingOrdersdLjava/util/HashMap;>;compactDrawingOrderLjava/util/List;0Ljava/util/List;availableAnimationsAndDatavLjava/util/HashMap;>;availableFaces]Ljava/util/HashMap;>;compositionTypes[Ljava/util/HashMap;$assertionsDisabledZ'(Ljava/lang/String;Ljava/lang/String;)VCodeLineNumberTableloadResourcesForClient()VloadResourcesForServergetDrawingOrders()Ljava/util/HashMap;f()Ljava/util/HashMap;>;getDrawingOrder1(Lcommunication/enums/Direction;)Ljava/util/List;Q(Lcommunication/enums/Direction;)Ljava/util/List;getCompactDrawingOrder()Ljava/util/List;2()Ljava/util/List;getAvailableAnimations5(Lcommunication/enums/CharacterClass;)Ljava/util/Set;I(Lcommunication/enums/CharacterClass;)Ljava/util/Set;getAnimationDataN(Lcommunication/enums/CharacterClass;Ljava/lang/String;)Lclient/AnimationData;getAvailableFaces6(Lcommunication/enums/CharacterClass;)Ljava/util/List;J(Lcommunication/enums/CharacterClass;)Ljava/util/List;getCompositionTypeH(Lcommunication/enums/CharacterClass;)Lcommunication/enums/AniCompoType;loadAvailableAnimations(Z)V StackMapTable<8=>loadAvailableFacesloadCompositionTypesloadDrawingOrders loadImages?@ABcountAvailableFrames(Ljava/lang/String;)IdetermineEndTypeX(Lcommunication/enums/CharacterClass;Ljava/lang/String;)Lcommunication/enums/AniEndType;0(addBone(Lcommunication/enums/CharacterClass;Ljava/lang/String;Lcommunication/enums/BodyPart;Lcommunication/enums/Direction;Lclient/Bone;)VgetBone(Lcommunication/enums/CharacterClass;Ljava/lang/String;Lcommunication/enums/BodyPart;Lcommunication/enums/Direction;)Lclient/Bone; SourceFileGraphicsContentManager.java tu vujava/util/ArrayList }~ CD EFjava/util/HashMap wx {x x x x GHjava/util/List IJclient/AnimationData communication/enums/AniCompoType= KL java/io/Filejava/lang/StringBuilder MN OP QR ST UV WPfaces XF YZ M[/ /body/down/down \ ]^ Animation  of  has M_ frames.` aQ b cd/faces /stand/body ef gf has limbed graphics. has compact graphics. CZcommunication/enums/BodyPart hD iD jD kD lD mDn opB qr sr tr ur v wx? yf z{java/lang/String |} K~ Kcouldn't load load  client/Bone 0* WARNING: Animation  hasn't any pictures!CWARNING: Couldn't find neither single picture nor animation frames!/aniSettings.txt java/lang/AssertionErrorjava/io/BufferedReaderjava/io/InputStreamReaderjava/io/FileInputStream    P java/io/IOException%Couldn't read settings for animation ! should be of AniEndType "".  F$communication/GraphicsContentManager fjava/lang/Object%[Lcommunication/enums/CharacterClass;"communication/enums/CharacterClass[Ljava/io/File;java/util/Iterator[Lcommunication/enums/BodyPart; [Lcommunication/enums/Direction;communication/enums/DirectioncompactLcommunication/enums/BodyPart;add(Ljava/lang/Object;)Zget&(Ljava/lang/Object;)Ljava/lang/Object;keySet()Ljava/util/Set;values'()[Lcommunication/enums/CharacterClass;append-(Ljava/lang/String;)Ljava/lang/StringBuilder;toString()Ljava/lang/String;(Ljava/lang/String;)V client/ClientdirectoryFilterLjava/io/FileFilter; listFiles%(Ljava/io/FileFilter;)[Ljava/io/File;getNameequalslimbed"Lcommunication/enums/AniCompoType;-(Ljava/lang/Object;)Ljava/lang/StringBuilder;java/lang/SystemoutLjava/io/PrintStream;(I)Ljava/lang/StringBuilder;java/io/PrintStreamprintln$(ILcommunication/enums/AniEndType;)Vput8(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; isDirectory()ZexistsrightArmrightLegbodyheadleftLegleftArmjava/util/ArraysasList%([Ljava/lang/Object;)Ljava/util/List;leftLcommunication/enums/Direction;rightdownup java/util/Setiterator()Ljava/util/Iterator;hasNextnext()Ljava/lang/Object;numberOfFramesI!()[Lcommunication/enums/BodyPart;"()[Lcommunication/enums/Direction;((Ljava/lang/String;Ljava/lang/String;I)V(Ljava/io/File;)V(Ljava/io/InputStream;)V(Ljava/io/Reader;)VreadLineclosecommunication/enums/AniEndTypevalueOf4(Ljava/lang/String;)Lcommunication/enums/AniEndType; containsKeyjava/lang/ClassdesiredAssertionStatus!qs tuvuwxyz{xy|}~yxyxyxy3**+*,;< =>e*Y*W* Y * Y * * Y ** Y ** Y **6 C DE#F.G2H=IAJLKQL\M`NdOH * Y ** Y *T UVWX* [y$ * +_y*cy'*+ gy+*+ ,k$ *+oy$ *+sWM,>6I,2:YY* !:"#: Y ::  6 6     2:  $:  %&6*'-Y*() * :*Y*() + :*,6-Y. /(012 3* 4:Y5: 6W *6WZ}~8BKPjq{~'4>DP}VO Q ^&: . L+=>+2:YY*7 !:"#:IY::6 6   ! 2:  $:  W *6Wt2 :DLUovK B $ L+=>+2:YY*8 !:95:--Y(; 3*'6W*-Y(< 3*=6Wk& :Jdt j&>Y?SY@SYASYBSYCSYDSEL* F+6W>YDSYCSYASYBSY@SY?SEM* G,6W>YASYCSY@SYDSY?SYBSEN* H-6W>YASYCSY@SYDSY?SYBSE:* I6W& -9froL+=>c+2:*:*JK:L3MN:*O:P6 Y*()) : Q:  6 6     2:==R:662:&Y ()( :Y ( : }Y* :Y!: -YS 3-YT 3UYV:*W YX* :Y!: -YS 3v-YTY* 3UY* dZ:*W,-Y[/(\ 3n 'Ʉ&!DNU|6E_b| -0Y_ehn $Z  8H5MI(dYY+* !M,:>YY+1* !:  -]3&   &(NTX`b&+ ,ɻYY*+(),^ !N_-: `YabYcYdY-efg:h:i.:-Yk,/+(l 3-Y.,/+(mn 3o@dgj. +@ X!_"d&g#i$%'(@f* * + : Y :* +6W, : Y :,6W- : Y :-6W_p `Ya6W>, -./&11263?4H6S7X8a9j;<=&!!C* + :, :- :U@ ABC&D1E8F5qr_+ @Faunis/bin/communication/MapInfo.class0000664000175000017500000000123112063430423017012 0ustar useruser2   serialVersionUIDJ ConstantValuemapNameLjava/lang/String;playersLjava/util/HashMap; SignatureLLjava/util/HashMap;((Ljava/lang/String;Ljava/util/HashMap;)VCodeLineNumberTablea(Ljava/lang/String;Ljava/util/HashMap;)V SourceFile MapInfo.java  communication/MapInfojava/lang/Objectjava/io/Serializable()V!   3**+*,  Faunis/bin/communication/clientToButlerOrders/0000775000175000017500000000000012063430423020553 5ustar useruserFaunis/bin/communication/clientToButlerOrders/CBOrder.class0000664000175000017500000000047312063430422023065 0ustar useruser2 serialVersionUIDJ ConstantValue()VCodeLineNumberTable SourceFile CBOrder.java *communication/clientToButlerOrders/CBOrderjava/lang/Objectjava/io/Serializable!  * Faunis/bin/communication/clientToButlerOrders/CBMoveOrder.class0000664000175000017500000000102112063430423023703 0ustar useruser2   serialVersionUIDJ ConstantValuexTargetIyTarget(II)VCodeLineNumberTable getXTarget()I getYTarget SourceFileCBMoveOrder.java  .communication/clientToButlerOrders/CBMoveOrder*communication/clientToButlerOrders/CBOrder()V!   3*** *!*%Faunis/bin/communication/clientToButlerOrders/CBCreatePlayerOrder.class0000664000175000017500000000077412063430423025373 0ustar useruser2  serialVersionUIDJ ConstantValue playerNameLjava/lang/String;(Ljava/lang/String;)VCodeLineNumberTable getPlayerName()Ljava/lang/String; SourceFileCBCreatePlayerOrder.java  6communication/clientToButlerOrders/CBCreatePlayerOrder*communication/clientToButlerOrders/CBOrder()V!  * **+ * Faunis/bin/communication/clientToButlerOrders/CBLoginOrder.class0000664000175000017500000000112312063430423024050 0ustar useruser2   serialVersionUIDJ ConstantValuenameLjava/lang/String;password'(Ljava/lang/String;Ljava/lang/String;)VCodeLineNumberTablegetName()Ljava/lang/String; getPassword SourceFileCBLoginOrder.java  /communication/clientToButlerOrders/CBLoginOrder*communication/clientToButlerOrders/CBOrder()V!   3**+*,  *%*+Faunis/bin/communication/clientToButlerOrders/CBChatOrder.class0000664000175000017500000000112312063430423023657 0ustar useruser2   serialVersionUIDJ ConstantValuemessageLjava/lang/String;toName'(Ljava/lang/String;Ljava/lang/String;)VCodeLineNumberTable getMessage()Ljava/lang/String; getToName SourceFileCBChatOrder.java  .communication/clientToButlerOrders/CBChatOrder*communication/clientToButlerOrders/CBOrder()V!   3**+*, *"*&Faunis/bin/communication/clientToButlerOrders/CBServerSourceOrder.class0000664000175000017500000000052112063430423025430 0ustar useruser2 serialVersionUIDJ ConstantValue()VCodeLineNumberTable SourceFileCBServerSourceOrder.java 6communication/clientToButlerOrders/CBServerSourceOrder*communication/clientToButlerOrders/CBOrder!  *  Faunis/bin/communication/clientToButlerOrders/CBDisconnectOrder.class0000664000175000017500000000051512063430423025075 0ustar useruser2 serialVersionUIDJ ConstantValue()VCodeLineNumberTable SourceFileCBDisconnectOrder.java 4communication/clientToButlerOrders/CBDisconnectOrder*communication/clientToButlerOrders/CBOrder!  *  Faunis/bin/communication/clientToButlerOrders/CBUnloadPlayerOrder.class0000664000175000017500000000052112063430423025400 0ustar useruser2 serialVersionUIDJ ConstantValue()VCodeLineNumberTable SourceFileCBUnloadPlayerOrder.java 6communication/clientToButlerOrders/CBUnloadPlayerOrder*communication/clientToButlerOrders/CBOrder!  *  Faunis/bin/communication/clientToButlerOrders/CBLoadPlayerOrder.class0000664000175000017500000000077012063430423025043 0ustar useruser2  serialVersionUIDJ ConstantValue playerNameLjava/lang/String;(Ljava/lang/String;)VCodeLineNumberTable getPlayerName()Ljava/lang/String; SourceFileCBLoadPlayerOrder.java  4communication/clientToButlerOrders/CBLoadPlayerOrder*communication/clientToButlerOrders/CBOrder()V!  * **+ * Faunis/bin/communication/clientToButlerOrders/CBTriggerEmoteOrder.class0000664000175000017500000000076212063430423025405 0ustar useruser2  serialVersionUIDJ ConstantValue]j2wemoteLjava/lang/String;(Ljava/lang/String;)VCodeLineNumberTablegetEmote()Ljava/lang/String; SourceFileCBTriggerEmoteOrder.java  6communication/clientToButlerOrders/CBTriggerEmoteOrder*communication/clientToButlerOrders/CBOrder()V!  * **+ * Faunis/bin/communication/clientToButlerOrders/CBLogoutOrder.class0000664000175000017500000000050512063430423024254 0ustar useruser2 serialVersionUIDJ ConstantValue()VCodeLineNumberTable SourceFileCBLogoutOrder.java 0communication/clientToButlerOrders/CBLogoutOrder*communication/clientToButlerOrders/CBOrder!  *  Faunis/bin/communication/movement/0000775000175000017500000000000012063430423016267 5ustar useruserFaunis/bin/communication/movement/Moveable.class0000664000175000017500000000052712063430422021053 0ustar useruser2hasPath()Z resetPath()VgetX()IgetY moveAbsolute(IIZ)VgetPath()Lcommunication/movement/Path;setPath (Lcommunication/movement/Path;)V SourceFile Moveable.javacommunication/movement/Moveablejava/lang/Object   Faunis/bin/communication/movement/MovingTask$1.class0000664000175000017500000000140412063430423021524 0ustar useruser2/        #($SwitchMap$communication$enums$Direction[I()VCodeLineNumberTable StackMapTable SourceFileMovingTask.javaEnclosingMethod$% &' () *+java/lang/NoSuchFieldError ,) -) .)#communication/movement/MovingTask$1 InnerClassesjava/lang/Object!communication/movement/MovingTaskcommunication/enums/Directionvalues"()[Lcommunication/enums/Direction;leftLcommunication/enums/Direction;ordinal()Irightupdown   F OKOKOKOK #&'256ADuWMMM"  Faunis/bin/communication/movement/Mover.class0000664000175000017500000000236312063430422020411 0ustar useruser2; ' ( ) *+ ' , - . /0 0 1234parent%Lcommunication/movement/MoverManager;moveable!Lcommunication/movement/Moveable;timerLjava/util/Timer; movingTask#Lcommunication/movement/MovingTask;intervalJJ(Lcommunication/movement/MoverManager;Lcommunication/movement/Moveable;J)VCodeLineNumberTable setMovingTask&(Lcommunication/movement/MovingTask;)Vstart()V getMoveable#()Lcommunication/movement/Moveable;stopstopAndUnregister SourceFile Mover.java    java/util/Timer   567 # 8 9:communication/movement/Moverjava/lang/ObjectscheduleAtFixedRate(Ljava/util/TimerTask;JJ)V!communication/movement/MovingTask#communication/movement/MoverManagerunregisterMover$(Lcommunication/movement/Moveable;)V! K**+*,*!*Y"# $%&'"*+ *+ -** *  23!"*6# $*  :;$ 2* ** >?@%&Faunis/bin/communication/movement/PathFactory.class0000664000175000017500000000245212063430423021545 0ustar useruser2R %& % '( ')* + , - ./ % 012 %3 4 5 5 678 9:;$assertionsDisabledZ()VCodeLineNumberTablecreateAirlinePath#(IIII)Lcommunication/movement/Path; StackMapTable& SourceFilePathFactory.java communication/movement/Path< => ?@java/awt/Point A BC  DEjava/lang/AssertionErrorF GHjava/lang/StringBuilderPath= IJ KLM NO"communication/movement/PathFactoryP QEjava/lang/Objectjava/lang/Mathabs(I)Isignum(F)F(II)Vpush(Ljava/awt/Point;)VisEmpty()Zjava/lang/SystemoutLjava/io/PrintStream;append-(Ljava/lang/String;)Ljava/lang/StringBuilder;toString()Ljava/lang/String;java/io/PrintStreamprintln(Ljava/lang/String;)Vjava/lang/ClassdesiredAssertionStatus!* ) Y:66 dd6d6'b6Y:  $b6Y:    Y YJ  ! '!4"A#N$U%X&e'r(y*|+,- ! < "5   @#$Faunis/bin/communication/movement/MoverManager.class0000664000175000017500000000037712063430422021707 0ustar useruser2   unregisterMover$(Lcommunication/movement/Moveable;)VgetSynchroStuffForMoverStop()[Ljava/lang/Object; SourceFileMoverManager.java#communication/movement/MoverManagerjava/lang/ObjectFaunis/bin/communication/movement/SoftMovingTask.class0000664000175000017500000000437012063430423022240 0ustar useruser2 5 6 78 9: ; <= >? @ A BCD E FG 8 H 9I J KL M KN O P Q R 9ST UVW$assertionsDisabledZB(Lcommunication/movement/Mover;Lcommunication/movement/Moveable;)VCodeLineNumberTableisMovementFinished()Zmove()V StackMapTableX=YZ[\T] SourceFileSoftMovingTask.java !" ^_` abZ c& de f client/PlayerGraphics  java/lang/AssertionError !( ghi gj client/Client klY mn on pq rs[ tu vn wu xn yz {| }~ q%communication/movement/SoftMovingTask &!communication/movement/MovingTaskjava/lang/Objectclient/ClientSettingscommunication/movement/Pathjava/awt/Pointcommunication/enums/Directionjava/lang/Throwablemoveable!Lcommunication/movement/Moveable;communication/movement/MoveablegetPath()Lcommunication/movement/Path;isEmptyrunningMutexKeyLjava/lang/Object; stopRunningparentLcommunication/movement/Mover;communication/movement/Mover%Lcommunication/movement/MoverManager;getClientSettings()Lclient/ClientSettings;deltaLevelAmplitude()I getDeltaLeveltop()Ljava/awt/Point; setDeltaLevel(I)VxIgetXygetYdeltaToDirection#(II)Lcommunication/enums/Direction; setDirection"(Lcommunication/enums/Direction;)V moveAbsolute(IIZ)Vpopjava/lang/ClassdesiredAssertionStatus! !"##*+,$ %'%&#% *$+'(#\ 2*YL*YM*,+ñ*N- Y * :6-: Y -6: Y -~,+ñ0-d-d:  - -F9t6- Y -W -,ç : , +ç : + "**'**.*$!01234"546F7M8S9f:l;s=@BCEHJLNOPQSTUV WY[%\1])L**+1,-$.)/$0**D1D12(#5$") @34Faunis/bin/communication/movement/RoughMovingTask.class0000664000175000017500000000260612063430423022411 0ustar useruser2N $ % &' () * + ,- . (/ 01 02 &34 567$assertionsDisabledZB(Lcommunication/movement/Mover;Lcommunication/movement/Moveable;)VCodeLineNumberTableisMovementFinished()Zmove()V StackMapTable89:4; SourceFileRoughMovingTask.java  <=> ?@9 A BC D java/lang/AssertionError  EF: GH IH JK&communication/movement/RoughMovingTaskL M!communication/movement/MovingTaskjava/lang/Objectcommunication/movement/Pathjava/awt/Pointjava/lang/Throwablemoveable!Lcommunication/movement/Moveable;communication/movement/MoveablegetPath()Lcommunication/movement/Path;isEmptyrunningMutexKeyLjava/lang/Object; stopRunningpop()Ljava/awt/Point;xIy moveAbsolute(IIZ)Vjava/lang/ClassdesiredAssertionStatus!#*+, % *"5s*YL*YM*,+ñ*N- Y - :,+ñ*   ,ç :,+ç :+_C_F\__c_kEkFhkkok6 '()*+$,6-<.A0F2Z4f5r64 D !5 @"#Faunis/bin/communication/movement/MovingTask.class0000664000175000017500000000632312063430423021404 0ustar useruser2 &I $J $KL I $M $N $O $P QR ST $UV I WXY Z[ Q\]^_ ` Qa bc de fg hi hj hk hlm n 'o hpqr stuv InnerClassesrunningMutexKeyLjava/lang/Object; stopRunningZparentLcommunication/movement/Mover;moveable!Lcommunication/movement/Moveable;$assertionsDisabledB(Lcommunication/movement/Mover;Lcommunication/movement/Moveable;)VCodeLineNumberTablerun()V StackMapTableLwxisMovementFinished()ZmovestoprdeltaToDirection#(II)Lcommunication/enums/Direction;directionToDelta1(Lcommunication/enums/Direction;)Ljava/awt/Point; SourceFileMovingTask.java 38 ./ 01java/lang/Object *+ ,- => ?8y .z{ |} 2-java/lang/AssertionError~ /Synchronized on movingPlayerGraphics, moveable. 8GSynchronized on movingPlayerGraphics, animatedPlayerGraphics, moveable.java/lang/RuntimeException+MovingTask: Lists array is of strange size! 3  8 8  java/awt/Point 3 $directionToDelta: Unknown direction!!communication/movement/MovingTask >java/util/TimerTask#communication/movement/MovingTask$1java/lang/Throwable[Ljava/lang/Object;communication/movement/Mover%Lcommunication/movement/MoverManager;#communication/movement/MoverManagergetSynchroStuffForMoverStop()[Ljava/lang/Object;java/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintln(Ljava/lang/String;)VstopAndUnregistertimerLjava/util/Timer;java/util/Timercancelcommunication/movement/Moveable resetPathjava/lang/Mathabs(I)Icommunication/enums/DirectionleftLcommunication/enums/Direction;rightupdown(II)V($SwitchMap$communication$enums$Direction[Iordinal()Ijava/lang/ClassdesiredAssertionStatus!$&*+,-./012-345K**+*,*Y*6 !"#$785$ *YL* * +ñ+çM+,* L + Y+A+2YM*YN²* *-ç :-,ç :,f+V+2YM+2YN²*Y:* *ç :-ç :-,ç :, Y QillplJuxx|x6n012357,8>9D:J;Q<Y>`?g@sABCDEGHIJKLNQ9P:D;<(::D;D;/:::E;D;D; =>?8@85;**YL*+çM+,*YL*+çN+-'255856"W XYZ ['\0]:^9(A:;A:; BC5|/6. a bcdegi!j%k)l-n9 DE5f* Y !*".F(2<Y Y Y Y Y#6"stu4w>yH{R}\9% F855$% 69 @GH) '$Faunis/bin/communication/movement/Path.class0000664000175000017500000000312212063430423020210 0ustar useruser2e ;< ; => ; ? @A @BC D E F G H IJ ;K L M NO PQ RSTserialVersionUIDJ ConstantValuestepsLjava/util/LinkedList; Signature(Ljava/util/LinkedList;()VCodeLineNumberTablecopy()Lcommunication/movement/Path; StackMapTable>Upush(Ljava/awt/Point;)Vpop()Ljava/awt/Point;topisEmpty()ZtoString()Ljava/lang/String;J SourceFile Path.java &'java/util/LinkedList "#communication/movement/Path VWU X5 YZjava/awt/Point [Z /0 \] 45 1Z ^Zjava/lang/StringBuilder( _` ab _c, db) 67java/lang/Objectjava/io/Serializablejava/util/Iteratoriterator()Ljava/util/Iterator;hasNextnext()Ljava/lang/Object;cloneadd(Ljava/lang/Object;)Zpeekappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;xI(I)Ljava/lang/StringBuilder;y! "#$%&'(0**Y) !*+(k3YL*M,,  N+- +)%&#'1),-. /0(& *+ W) - .12(@** )3 4 6, 32(# * );45( *)?67(RYL*M,7,  N+W+-W+W+-W+W+)"DE#F*G3H:ICJML,8.<9:Faunis/bin/communication/enums/0000775000175000017500000000000012063430423015564 5ustar useruserFaunis/bin/communication/enums/Direction.class0000664000175000017500000000174012063430423020535 0ustar useruser25 & '() * + , - . / 01leftLcommunication/enums/Direction;rightupdown$VALUES [Lcommunication/enums/Direction;values"()[Lcommunication/enums/Direction;CodeLineNumberTablevalueOf3(Ljava/lang/String;)Lcommunication/enums/Direction;(Ljava/lang/String;I)V Signature()V1Ljava/lang/Enum; SourceFileDirection.java  23communication/enums/Direction 4      java/lang/Enumclone()Ljava/lang/Object;5(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;@1@@@@ "  # **+ !"!pTY Y  Y  YY SY SY SYS 4 #$%Faunis/bin/communication/enums/AniCompoType.class0000664000175000017500000000163512063430423021167 0ustar useruser2-  !"# $ % & ' ()limbed"Lcommunication/enums/AniCompoType;compact$VALUES#[Lcommunication/enums/AniCompoType;values%()[Lcommunication/enums/AniCompoType;CodeLineNumberTablevalueOf6(Ljava/lang/String;)Lcommunication/enums/AniCompoType;(Ljava/lang/String;I)V Signature()V4Ljava/lang/Enum; SourceFileAniCompoType.java  *+ communication/enums/AniCompoType ,    java/lang/Enumclone()Ljava/lang/Object;5(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;@1 @ @ "  # **+J.Y Y  Y SY S Faunis/bin/communication/enums/CharacterClass.class0000664000175000017500000000223612063430422021477 0ustar useruser2A / 01 2 3 4 5 6 7 8 9 : ; <=rodens$Lcommunication/enums/CharacterClass;melesarctosglauxcervuslynxaguila$VALUES%[Lcommunication/enums/CharacterClass;values'()[Lcommunication/enums/CharacterClass;CodeLineNumberTablevalueOf8(Ljava/lang/String;)Lcommunication/enums/CharacterClass;(Ljava/lang/String;I)V Signature()V6Ljava/lang/Enum; SourceFileCharacterClass.java   >?"communication/enums/CharacterClass %@ '( '(       java/lang/Enumclone()Ljava/lang/Object;5(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;@1@@@@@@@  !"#" $ %&## *$'(#*+$)*+*#Y Y  Y  YYYYY SY SY SYSYSYSYS$ \),-.Faunis/bin/communication/enums/ClientStatus.class0000664000175000017500000000210312063430422021230 0ustar useruser29 ) *+, - . / 0 1 2 3 45 disconnected"Lcommunication/enums/ClientStatus; loggedOut noCharLoaded exploringfighting$VALUES#[Lcommunication/enums/ClientStatus;values%()[Lcommunication/enums/ClientStatus;CodeLineNumberTablevalueOf6(Ljava/lang/String;)Lcommunication/enums/ClientStatus;(Ljava/lang/String;I)V Signature()V4Ljava/lang/Enum; SourceFileClientStatus.java  67 communication/enums/ClientStatus 8 !" !"     java/lang/Enumclone()Ljava/lang/Object;5(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;@1@@@@@ "   # *!"*+#$%$gY Y  Y  YYY SY SY SYSYS A#&'(Faunis/bin/communication/enums/BodyPart.class0000664000175000017500000000225412063430423020342 0ustar useruser2E 2 34#5 6 7 8 9 : ; < = > ?! @AbodyLcommunication/enums/BodyPart;headleftArmrightArmleftLegrightLegtailcompact$VALUES[Lcommunication/enums/BodyPart;values!()[Lcommunication/enums/BodyPart;CodeLineNumberTablevalueOf2(Ljava/lang/String;)Lcommunication/enums/BodyPart;(Ljava/lang/String;I)V Signature()V0Ljava/lang/Enum; SourceFile BodyPart.java "## BCcommunication/enums/BodyPart (D *+ *+        !java/lang/Enumclone()Ljava/lang/Object;5(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;@1 @@@@@@@ @!"# $%&" ' ()&# *'*+&*+',-.-&Y Y  Y  YYYYYY SY SY SYSYSYSYSYS' j,/01Faunis/bin/communication/enums/AniEndType.class0000664000175000017500000000167412063430423020623 0ustar useruser21 # $%& ' ( ) * + ,-revert Lcommunication/enums/AniEndType;repeatend$VALUES![Lcommunication/enums/AniEndType;values#()[Lcommunication/enums/AniEndType;CodeLineNumberTablevalueOf4(Ljava/lang/String;)Lcommunication/enums/AniEndType;(Ljava/lang/String;I)V Signature()V2Ljava/lang/Enum; SourceFileAniEndType.java  ./communication/enums/AniEndType 0     java/lang/Enumclone()Ljava/lang/Object;5(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;@1@@@ "  # **+]AY Y  Y  Y SY SY S ' !"Faunis/bin/client/0000775000175000017500000000000012063430423013046 5ustar useruserFaunis/bin/client/Animator.class0000664000175000017500000000327412063430422015654 0ustar useruser2] < = >? < @A B CD E F G H I J K LM N OPQR InnerClasses AnimatingTaskrunningMutexKeyLjava/lang/Object; stopRunningZparentLclient/AnimatorManager; animateableLclient/Animateable;timerLjava/util/Timer; animatingTaskLclient/Animator$AnimatingTask;endType Lcommunication/enums/AniEndType;intervalJ maxFrameIndexIQ(Lclient/AnimatorManager;Lclient/Animateable;JLcommunication/enums/AniEndType;I)VCodeLineNumberTablestart()VgetAnimateable()Lclient/Animateable;stop StackMapTableQDSstopAndUnregister SourceFile Animator.java ,1  !java/util/Timer "#client/Animator$AnimatingTask ,T $%java/lang/Object   &' () *+ UV W1X Y1 41Z [\client/Animatorclient/Animator$1java/lang/Throwable(Lclient/Animator;)VscheduleAtFixedRate(Ljava/util/TimerTask;JJ)Vcancelclient/Animateable resetEmoteclient/AnimatorManagerunregisterAnimator(Lclient/Animateable;)V!  !"#$%&'()*+,-.G**+*,*Y*Y* * Y * * *!*/. '( )*+%,0-5.;/@0F101.-** */ 8923.*/<41.8** YL* +çM+,*YL*+çN+-$/2252/"BCDEF$G-H7I5(67867891.2***/LMN:;Faunis/bin/client/Client$1.class0000664000175000017500000000064612063430422015445 0ustar useruser2  ()VCodeLineNumberTableaccept(Ljava/io/File;)Z SourceFile Client.javaEnclosingMethod  client/Client$1 InnerClassesjava/lang/Objectjava/io/FileFilter client/Client java/io/File isDirectory()Z0* A + D   Faunis/bin/client/Client.class0000664000175000017500000004430512063430422015320 0ustar useruser2                            &    +     & 2 &    ;   ; @ @ ? @   ; J  ; N  R   Z Z Z J Z  i  m                   {  }  q 5 q & 5  5 5  u  ! &" s s# 5$ @%& 5'() 5* +,- . / i01 2 i3 i4567 58 9 :; :<d m= m> &? @A BC BDE &F wG HI wJ HKL yM N OP NQRS TUV  WXY Z[ \ ]^ _`a bcd ef bg hijkl mno bpq rst  &u vA wx yz{  |}~ServerRunnable InnerClassesconnectionModiMutexKeyLjava/lang/Object;connectionModiOccupiedZ clientStatus"Lcommunication/enums/ClientStatus;clientSettingsLclient/ClientSettings;graphicsContentManager&Lcommunication/GraphicsContentManager;socketLjava/net/Socket;outputLjava/io/ObjectOutputStream;inputLjava/io/ObjectInputStream;winLclient/GameWindow;activePlayerNameLjava/lang/String;currentMapNamecurrentPlayersLjava/util/HashMap; Signature>Ljava/util/HashMap;movingPlayerGraphicsJLjava/util/HashMap;animatedPlayerGraphics=Ljava/util/HashMap; serverThreadLjava/lang/Thread;serverRunnableLclient/Client$ServerRunnable;stopServerThreaddirectoryFilterLjava/io/FileFilter;$assertionsDisabled()VCodeLineNumberTablemain([Ljava/lang/String;)Vrun StackMapTableinitEgetPlayerGraphics+(Ljava/lang/String;)Lclient/PlayerGraphics;getCurrentMapName()Ljava/lang/String;getCurrentPlayerNamegetClientSettings()Lclient/ClientSettings;getSynchroStuffForMoverStop()[Ljava/lang/Object;getSynchroStuffForAnimatorStop()Ljava/lang/Object;getGraphicsContentManager(()Lcommunication/GraphicsContentManager;getClientStatus$()Lcommunication/enums/ClientStatus;connect()Z disconnecttryStopMovement(Lclient/PlayerGraphics;)VtryStopAnimationhandleServerOrder/(Lcommunication/butlerToClientOrders/BCOrder;)VshowChatMessage:(Lcommunication/butlerToClientOrders/BCChatMessageOrder;)VlogErrorMessage;(Lcommunication/butlerToClientOrders/BCErrorMessageOrder;)V(Ljava/lang/String;)VlogSystemMessage<(Lcommunication/butlerToClientOrders/BCSystemMessageOrder;)VaddChar6(Lcommunication/butlerToClientOrders/BCAddCharOrder;)VL removeChar9(Lcommunication/butlerToClientOrders/BCRemoveCharOrder;)V changeChar9(Lcommunication/butlerToClientOrders/BCChangeCharOrder;)VtryStartMovementtryStartAnimation,(Lclient/PlayerGraphics;Ljava/lang/String;)V unloadMapsetMap5(Lcommunication/butlerToClientOrders/BCSetMapOrder;)VsetClientStatus>(Lcommunication/butlerToClientOrders/BCSetClientStatusOrder;)V sendOrder/(Lcommunication/clientToButlerOrders/CBOrder;)Z parseCommand((Ljava/lang/String;[Ljava/lang/String;)ZjunregisterMover$(Lcommunication/movement/Moveable;)VunregisterAnimator(Lclient/Animateable;)VgetAllGraphicsToDraw()Ljava/util/ArrayList;t0()Ljava/util/ArrayList;concatenateHelper(([Ljava/lang/String;I)Ljava/lang/String; access$0027(Lclient/Client;Lclient/GameWindow;)Lclient/GameWindow; access$000$(Lclient/Client;)Lclient/GameWindow; SourceFile Client.java  )* client/Client 1*     * *java/lang/Object   %   client/Client$2 ) java/lang/InterruptedException *+java/lang/reflect/InvocationTargetExceptionWelcome to Faunis! UT(Copyright 2012 Simon Ley alias "skarute"#Licensed under GNU AGPL v3 or laterclient/ClientSettings : RT$communication/GraphicsContentManager : : )   *java/util/HashMap   client/Client$ServerRunnable ) #$ FG /* ( java/lang/AssertionError client/PlayerGraphics  ACouldn't connect since clientStatus is not set to "disconnected"!  Gjava/net/Socket :  )java/lang/Exceptionjava/lang/StringBuilder3Socket to game server couldn't be created! Reason:  : : Socket created. T'Try to create input / output streams...java/io/ObjectInputStream  ) java/io/ObjectOutputStream  ) java/io/IOExceptionCouldn't create input / output!  !Input / output have been created.Start serverThread... !" Gjava/lang/Threadclient_serverThread ) *Client: called disconnect();Client: disconnect(): Connection is already being modified?EClient: Couldn't disconnect as clientStatus is already "disconnected" *Couldn't choke serverThread! 'disconnect(): Caller isn't serverThread Client: serverThread terminated.$disconnect(): Caller is serverThread f*(Client: Connection to server terminated.communication/movement/Mover * vwMovement stopped.client/Animator yzAnimation stopped.1communication/butlerToClientOrders/BCAddCharOrder WX4communication/butlerToClientOrders/BCChangeCharOrder `a4communication/butlerToClientOrders/BCRemoveCharOrder ]^0communication/butlerToClientOrders/BCSetMapOrder hi9communication/butlerToClientOrders/BCSetClientStatusOrder lm6communication/butlerToClientOrders/BCErrorMessageOrder RS7communication/butlerToClientOrders/BCSystemMessageOrder UV5communication/butlerToClientOrders/BCChatMessageOrder PQReceived unknown server order! Gclient/SwingMessageRunnable :: :  )  ERROR:    ) :  G cL G : de KL ML old x=  , y= new x=There already exists a Mover!  GStart movement... T  )%communication/movement/SoftMovingTask ) ) movement started. Start animation too...walk There already exists a Animator!Start animation...     ) animation started.   G Ajava/lang/String *   : #communication/GraphicalPlayerStatus E   8Client: Couldn't send order since there's no connection! Error while sending ClientOrder/c /i/communication/clientToButlerOrders/CBLoginOrder pq/o0communication/clientToButlerOrders/CBLogoutOrder/x4communication/clientToButlerOrders/CBDisconnectOrder/w .communication/clientToButlerOrders/CBChatOrder/b/l4communication/clientToButlerOrders/CBLoadPlayerOrder )T/u6communication/clientToButlerOrders/CBUnloadPlayerOrder/n6communication/clientToButlerOrders/CBCreatePlayerOrder/m java/lang/NumberFormatException Error while parsing the numbers..communication/clientToButlerOrders/CBMoveOrder )/e6communication/clientToButlerOrders/CBTriggerEmoteOrder/s6communication/clientToButlerOrders/CBServerSourceOrder Command couldn't be interpreted.Unregistering Mover...java/util/ArrayList    Gclient/Client$1 &'#communication/movement/MoverManagerclient/AnimatorManagerjava/lang/Throwablejava/util/Iteratorcommunication/MapInfo communication/enums/ClientStatus*communication/clientToButlerOrders/CBOrdercommunication/movement/Moveableclient/AnimateabledelayBetweenFrames()Iclient/GraphWindelay(J)Vclient/GameWindowdrawrepaint disconnected(Lclient/Client;)Vjavax/swing/SwingUtilities invokeAndWait(Ljava/lang/Runnable;)VprintStackTrace checkPathsplayerGraphicsPathimageFileEnding'(Ljava/lang/String;Ljava/lang/String;)VloadResourcesForClient!(Lclient/Client;Lclient/Client;)V containsKey(Ljava/lang/Object;)Zget&(Ljava/lang/Object;)Ljava/lang/Object;isClosedhostport(Ljava/lang/String;I)Vappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;getLocalizedMessagetoStringjava/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintlngetInputStream()Ljava/io/InputStream;(Ljava/io/InputStream;)VgetOutputStream()Ljava/io/OutputStream;(Ljava/io/OutputStream;)V loggedOutisAlive)(Ljava/lang/Runnable;Ljava/lang/String;)Vstartclose currentThread()Ljava/lang/Thread;stop isBroadcast getFromName getMessageclient/MessageType broadcastLclient/MessageType;<(Ljava/lang/String;Lclient/MessageType;Lclient/GameWindow;)V invokeLaterwhispererrorsystemgetGraphStatus'()Lcommunication/GraphicalPlayerStatus;7(Lcommunication/GraphicalPlayerStatus;Lclient/Client;)V getPlayerNameput8(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;hasPathhasEmotegetEmoteremovegetX(I)Ljava/lang/StringBuilder;getYgetPath()Lcommunication/movement/Path;communication/movement/PathisEmptyprintnumberOfDeltaLevelStatesJ(Lcommunication/movement/MoverManager;Lcommunication/movement/Moveable;J)VB(Lcommunication/movement/Mover;Lcommunication/movement/Moveable;)V setMovingTask&(Lcommunication/movement/MovingTask;)VgetType&()Lcommunication/enums/CharacterClass;getAnimationDataN(Lcommunication/enums/CharacterClass;Ljava/lang/String;)Lclient/AnimationData;client/AnimationDataendType Lcommunication/enums/AniEndType;numberOfFramesIQ(Lclient/AnimatorManager;Lclient/Animateable;JLcommunication/enums/AniEndType;I)VkeySet()Ljava/util/Set; java/util/Setiterator()Ljava/util/Iterator;hasNextnextclear getMapInfo()Lcommunication/MapInfo;mapNamegetActivePlayerNameplayers getNewStatus exploringfighting writeObject(Ljava/lang/Object;)Vequalsjava/lang/IntegerparseInt(Ljava/lang/String;)I(II)Vvalues()Ljava/util/Collection;java/util/Collectionaddjava/lang/ClassdesiredAssertionStatus!       !"#$%&'(')*+!*, / -.+' Y, I J/*+E** * ,N PQ01*+d* Y * **Y*L+L+****Y*L+*+* Y*!*"#$*$%*&Y'(*&Y')*&Y'**+Y**,-*.W*/'*'2,nW XY\d'p*j+l/p2m3o7q=rCsIvTx\y`ze}~0j2G3-456+y3*(YM²0*(+1 2Y3*(+45,ðN,--..1., .0  7M89:+*6,;:+*7,<=+*,>?++ Y*)SY**S,@A+$  Y**S,BC+*$,DE+*,FG+oL* YL* +ì* +çM+,*YL**8* +ì0*9*9: 2Y3*;Y*<*=>9'M*@YABC,DCE* +ìFGHFIH*JY*9KLM*NY*9OPQM,S*T* +ì*UFVHFWH*0*X*XY 2Y3*ZY*-[\X*X]* +ìN+- `y|?R(@GAGGFGGJG,%!(28=A`y|}&7>CG0% 7I87[H#vI:`8JG+F^H* YL* F_H+ì* +çM+,*YL**`* +ì0*XY 2Y3**MaM,SFbHc*X;FdH*XY0*XY 2Y3FeH FfH**g**M*Q*X* FhH+ìN+-!,"),,/,nuxR8PQ,#"'18BHMQinuxy}    0$ "7I87NI   o8KL+ ^*)YM**YN+Y:*)+4i:j*+kFlHç :-ç :-,ç :,:==B=GJJNJSVVZV,2 9:;< =%>*?/A7CEDQE]F0#7777E8D8D8ML+H**YM+YN**+4m:n*+oFpH-ç :-,ç :, 14484=@@D@,* KL MNO"P'R/T;UGV0/77D8D8NO+0+ 2Y3+q*+qr+s*+stw+u*+uve+w*+wxS+y*+yzA+{*+{|/+}*+}~+*+ FH,NYZ[$\+]6^=_H`OaZbacldse~fghikn0 PQ+g+4Y@YA+CC+CE*1Y@YA+CC+CE*,qr8vfz08-RS+% *+, }~RT+A%Y@YAC+CE*, $UV+% *+, UT+/Y+*, WX+p+M5Y,*N+:*(Y:²0*(1 2Y3*(-Wç :- *-- *--EHHMH,2 7BPW_fo0$7YZ[\47P8]^++M*(Y:²0*(,1 2Y3*(,45Nç :*-*-*(Y:²0*(,1 2Y3*(,Wç : 588=8Rwzzz,2  &2@EJRkt00&47Q8Y_4\*7N8`a+ +M5Y,*N+::*(Y:²0*(1 2Y3*(45:ç :F@YACCEHF@YAC-C-EH***(Y:²0*(1 2Y3*(-Wç :- *-- *-- KNNSN,V :HV04:Yb[\4\7S87P8cL+ *)YM**YN+Y:*)+1FH-,ñ+b+XF*6iY*+l:Y+:*)+WFH*+ç :-ç : - ,ç : , ).+.-.,R&.?GPbnu0&.777eE8D8D8de+5 **YN+Y:**+1FH-ñF*$+,::d6mY*+:**+WFHç :  -ç : -  "{%x{{{$%,B %-;BK]hmu0%77U8D8f*+p*(YL*)YM*(N-%-:*(45:**(*7*6,ç :,+ç :+Y\\`\ehhlh,2 / = C F M RWco077g*U8D8hi+8 +M*(YN*)Y:*g*,ĵ6*+ŵ7,ƶ:>:,4:5Y*:*(W*ç :  -ç : - ~ ,>  (LZ f!r"x#{$%&0,6Yjk77gDE8D8lm+c+M,*MaN-SFbH*YN*ɥ *ʦ,ɥ,ʥ*g*,-ç :- R+X[[_[,:*+ 15234#6$9+:M?QAVBbC0%YnoI 7I8pq+-d*YM* *˶,ì0*Q 2Y3*QYN*Q+̧:*Ͷ-,ì-,ì:-:,7?BR7MVPSVVZV]O]PU]Va],:KLMNP0Q7S?WBTDUJVPXVY]Z077Yr77I E8Yr78st++ζϙ *.W+жϙ#,,2N,2:*Y-ҶW+Զϙ*YֶW+׶ϙ*YٶW+ڶϙ%,,2N,:*Y-ݶW+޶ϙ,,N*Y-ݶW+߶ϙ,2N*Y-W+ϙ*YW+ϙ,,2N*Y-W+ϙ6,0,2>,26 :**YW+ϙN,,2N*Y-W+ϙ*YW**-,6_ `abc#d(e7f9gBhNiPjYkelgmvnzopqrstuvwxyz{|}~  "*-/57FHQSY]jlu0!(*$!`u 4vw+DFH0+5 2Y3+5M*)YN*,*),W-ç :-)9<<@<,"").7C0Yx\78yz+70+5 2Y3+5M**YN**,W-ç :-!,//3/,!*60Y{\78|}+QYL*(+*(YM*(N--5:+W,ç :,+EHHLH,9CO0~7gD8 +H0* 2Y3@YAM,*2CW`>*,CW,*2CW,E,"$.5=C0 +*+Z,/+*,/*+C0Y, /A0 @+Faunis/bin/client/GameWindow$CommandSendButtonListener.class0000664000175000017500000000271512063430422023221 0ustar useruser2Y ( ) * +, - ./ 01 2 34 )5 6 78 +9: ;<=@A$assertionsDisabledZthis$0Lclient/GameWindow;(Lclient/GameWindow;)VCodeLineNumberTableactionPerformed(Ljava/awt/event/ActionEvent;)V StackMapTable5B()V SourceFileGameWindow.java  % CDE FG HI JK/ LM NO java/lang/AssertionErrorjava/lang/String PQR ST UIclient/GameWindowV WX+client/GameWindow$CommandSendButtonListenerCommandSendButtonListener InnerClassesjava/lang/Objectjava/awt/event/ActionListener[Ljava/lang/String; commandEditLjavax/swing/JTextField;javax/swing/JTextFieldgetText()Ljava/lang/String;logOldCommandMessage(Ljava/lang/String;)Vlength()I startsWith(Ljava/lang/String;)Zsplit'(Ljava/lang/String;)[Ljava/lang/String;parentLclient/Client; client/Client parseCommand((Ljava/lang/String;[Ljava/lang/String;)ZsetTextjava/lang/ClassdesiredAssertionStatus()Z!" *+* *M*,,o,f, N - Y -2:-d:6-d-2S*6*6 #*=BKU`fv!="#"#$%5 ! @&'? >Faunis/bin/client/SwingMessageRunnable$1.class0000664000175000017500000000134212063430423020305 0ustar useruser2/        #$SwitchMap$client$MessageType[I()VCodeLineNumberTable StackMapTable SourceFileSwingMessageRunnable.javaEnclosingMethod$% &' () *+java/lang/NoSuchFieldError ,) -) .)client/SwingMessageRunnable$1 InnerClassesjava/lang/Objectclient/SwingMessageRunnableclient/MessageTypevalues()[Lclient/MessageType;errorLclient/MessageType;ordinal()Isystemwhisper broadcast   F OKOKOKOK #&'256AD!WMMM"  Faunis/bin/client/Bone.class0000664000175000017500000000664712063430423014775 0ustar useruser2 3[\ [ 0]^ _ `a bc def _ 0g 0h 0ij [ k l mn do p qrs [ t uv w x 0y z{| %} ~ 0  *[    zimagesLjava/util/ArrayList; Signature5Ljava/util/ArrayList;connectionOffsetsZLjava/util/ArrayList;>; translatorLclient/ColourBoneTranslator; isAnimationZ$assertionsDisabled(Ljava/lang/String;)VCodeLineNumberTable StackMapTablec((Ljava/lang/String;Ljava/lang/String;I)V^n()ZreadConnectionOffsets()VrsgetConnectionOffset1(Lcommunication/enums/BodyPart;I)Ljava/awt/Point;getConnectionOffsets(I)Ljava/util/Set;2(I)Ljava/util/Set;getImage!(I)Ljava/awt/image/BufferedImage;draw(Ljava/awt/Graphics;III)V SourceFile Bone.java ?Ljava/util/ArrayList 45 java/io/File ?@ java/lang/Exception Ljava/lang/RuntimeExceptionCouldn't load picture! <= 85 KLjava/lang/StringBuilder java/io/IOExceptionCouldn't load frame! java/awt/image/BufferedImagejava/util/HashMap java/awt/Color ? :; java/awt/Point ? >= java/lang/AssertionError java/awt/Image  client/Bone J java/lang/Objectjava/lang/Stringjavax/imageio/ImageIOread.(Ljava/io/File;)Ljava/awt/image/BufferedImage;add(Ljava/lang/Object;)ZprintStackTraceappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;(I)Ljava/lang/StringBuilder;toString()Ljava/lang/String;size()Iget(I)Ljava/lang/Object; getHeightgetWidthgetRGB(II)I(IZ)Vclient/ColourBoneTranslator translate0(Ljava/awt/Color;)Lcommunication/enums/BodyPart;(II)Vput8(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; containsKey&(Ljava/lang/Object;)Ljava/lang/Object;keySet()Ljava/util/Set;java/awt/Graphics drawImage3(Ljava/awt/Image;IILjava/awt/image/ImageObserver;)Zjava/lang/ClassdesiredAssertionStatus getInstance()Lclient/ColourBoneTranslator;!0345678569 :;<=>= ?@AM**YY+M,N*-WM, Y **Y*&) B6 +,./0&4)1*2.385=6H7L8C)DEF?GAx**Y6NYY+,::*W: Y **Y*8ILB>:;<=8??@IDLANBSC]<cGhHsIwJC2DEE9DEEHI<JA*BMKLA<*}*MYN6,N6,< Y,!":#$:-%Y&'W*-W~B:Q RS!U-V9WKXUYZZlVrUx^Q`C!MN ;OPAX3(*+) *Y+*+,%B c dC QRA'*-Bh6STUA$ *BlVWA1+*./WB pqXLA?01(2#B %(C @YZFaunis/bin/client/Client$ServerRunnable.class0000664000175000017500000000257412063430422020244 0ustar useruser2V ' ( ) *+ *, -./0 *1 *2 345 678 9:; *<=@AparentLclient/Client;this$0!(Lclient/Client;Lclient/Client;)VCodeLineNumberTablerun()V StackMapTable=@//8 SourceFile Client.java   B CD EFG HIjava/io/IOException"Couldn't read anymore from server! JK LMN OPserverRunnable ends.Q RK java/lang/ClassNotFoundException SClassNotFoundException!*communication/butlerToClientOrders/BCOrder TUclient/Client$ServerRunnableServerRunnable InnerClassesjava/lang/Objectjava/lang/Runnable client/ClientstopServerThreadZinputLjava/io/ObjectInputStream;java/io/ObjectInputStream readObject()Ljava/lang/Object;logErrorMessage(Ljava/lang/String;)V disconnect()Zjava/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintlnprintStackTracehandleServerOrder/(Lcommunication/butlerToClientOrders/BCOrder;)V /*+**,  n*^L*L5M* * * W  M,  ++*+    ?F# $ &/'($)6*>+?,@-D.L0W1b2e3m4. !"# !$ %&? *>Faunis/bin/client/SwingMessageRunnable.class0000664000175000017500000000176712063430423020173 0ustar useruser2; ! " # $ %& '( ') '* '+,-./ InnerClassesmessageLjava/lang/String;typeLclient/MessageType;winLclient/GameWindow;<(Ljava/lang/String;Lclient/MessageType;Lclient/GameWindow;)VCodeLineNumberTablerun()V StackMapTable SourceFileSwingMessageRunnable.java     012 345 67 87 97 :7client/SwingMessageRunnablejava/lang/Objectjava/lang/Runnableclient/SwingMessageRunnable$1$SwitchMap$client$MessageType[Iclient/MessageTypeordinal()Iclient/GameWindowlogErrorMessage(Ljava/lang/String;)VlogSystemMessagelogWhisperMessagelogBroadcastMessage!  <**+*,*- ^*.R+9G******* ** & !(#3$6&A'D)O*R,]/(   Faunis/bin/client/AnimatorManager.class0000664000175000017500000000035512063430422017144 0ustar useruser2   unregisterAnimator(Lclient/Animateable;)VgetSynchroStuffForAnimatorStop()Ljava/lang/Object; SourceFileAnimatorManager.javaclient/AnimatorManagerjava/lang/ObjectFaunis/bin/client/GameWindow.class0000664000175000017500000001743212063430422016144 0ustar useruser2                    !   &  & *  . *            H  H H                        l l _ _ _!"# _$  $  % &' () (*+ , l- . /0 l1 l2 3 l4 56 l7 89: 8; <= {>? @A BCDCommandSendButtonListener InnerClassesparentLclient/Client; commandPanelLjavax/swing/JPanel;loggingScrollPaneLjavax/swing/JScrollPane;loggingTextPaneLjavax/swing/JTextPane;loggingDocument!Ljavax/swing/text/StyledDocument;commandSendButtonLjavax/swing/JButton; commandEditLjavax/swing/JTextField;errorTextStyle%Ljavax/swing/text/SimpleAttributeSet;systemTextStylewhisperTextStyleoldCommandTextStylebroadcastTextStyle$assertionsDisabledZ&(Lclient/Client;IILjava/lang/String;)VCodeLineNumberTable StackMapTableAEFdraw()VGHI drawFieldGridwriteMapAndPlayerInfodrawClientStatusdrawAllPlayersJK+calculateDrawingOffset)(Lclient/PlayerGraphics;)Ljava/awt/Point; logMessage:(Ljava/lang/String;Ljavax/swing/text/SimpleAttributeSet;)V=logErrorMessage(Ljava/lang/String;)VlogWhisperMessagelogOldCommandMessagelogBroadcastMessagelogSystemMessage SourceFileGameWindow.java L #javax/swing/text/SimpleAttributeSet MNO PQ java/awt/Color R SN TN javax/swing/JTextPane UV WX YZ java/lang/AssertionErrorjavax/swing/JScrollPane [ java/awt/Dimension \ ]^javax/swing/JPaneljava/awt/BorderLayout _Center `ajavax/swing/JTextField javax/swing/JButtonSend +client/GameWindow$CommandSendButtonListener b cd `eSouth fgh ijk lm nop qst uv wxpackedy z {| }N~ X     java/awt/Point N   E H   N         java/lang/StringBuilder(  ,)  J K  client/PlayerGraphics            %javax/swing/text/BadLocationException -Error appending a message to the loggingPane! client/GameWindow client/GraphWin client/Clientjava/lang/Stringjava/lang/Object communication/enums/ClientStatusjava/lang/Throwablejava/util/ArrayListjava/util/Iterator(IILjava/lang/String;)VredLjava/awt/Color;javax/swing/text/StyleConstants setForeground9(Ljavax/swing/text/MutableAttributeSet;Ljava/awt/Color;)V(III)Vbluegray setEditable(Z)V setBackground(Ljava/awt/Color;)VgetStyledDocument#()Ljavax/swing/text/StyledDocument;(Ljava/awt/Component;)V(II)VsetPreferredSize(Ljava/awt/Dimension;)V(Ljava/awt/LayoutManager;)Vadd<(Ljava/lang/String;Ljava/awt/Component;)Ljava/awt/Component;(Lclient/GameWindow;)VaddActionListener"(Ljava/awt/event/ActionListener;)V*(Ljava/awt/Component;)Ljava/awt/Component;winLjavax/swing/JFrame;javax/swing/JFrame getRootPane()Ljavax/swing/JRootPane;javax/swing/JRootPanesetDefaultButton(Ljavax/swing/JButton;)VgetContentPane()Ljava/awt/Container;java/awt/Container drawingPanel DrawingPanelLclient/GraphWin$DrawingPanel;client/GraphWin$DrawingPanelpackjava/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintlngraphLjava/awt/Graphics;greenjava/awt/GraphicssetColorimgLjava/awt/image/BufferedImage;java/awt/image/BufferedImagegetWidth()I getHeightfillRect(IIII)VmousePos()Ljava/awt/Point;blackxIydrawRectgetClientStatus$()Lcommunication/enums/ClientStatus; exploring"Lcommunication/enums/ClientStatus;fighting lightGraygetClientSettings()Lclient/ClientSettings;client/ClientSettings fieldWidth fieldHeightgetCurrentMapName()Ljava/lang/String;getCurrentPlayerName drawString(Ljava/lang/String;II)VgetPlayerGraphics+(Ljava/lang/String;)Lclient/PlayerGraphics;getXgetYappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;(I)Ljava/lang/StringBuilder;toStringgetAllGraphicsToDraw()Ljava/util/ArrayList;iterator()Ljava/util/Iterator;hasNext()Znext()Ljava/lang/Object;getNamegetFontMetrics()Ljava/awt/FontMetrics;java/awt/FontMetrics stringWidth(Ljava/lang/String;)IgetFrame(Ljava/awt/Graphics;III)VnumberOfDeltaLevelStates getDirection!()Lcommunication/enums/Direction;!communication/movement/MovingTaskdirectionToDelta1(Lcommunication/enums/Direction;)Ljava/awt/Point; getDeltaLeveljavax/swing/text/StyledDocument getLength insertString5(ILjava/lang/String;Ljavax/swing/text/AttributeSet;)VsetCaretPosition(I)VprintStackTracejava/lang/ClassdesiredAssertionStatus! **+*Y**Y* Yxx *Y * *Y * *Y* YP *Y** Y *** Y*Y**Ydd Y!Y"#:$*%W*&Y'(*(Y,)**Y+,-*-.Y*/0* Y12*2*(3W*2*-3W Y!Y"#:$%W4*2%W*56*-7*5849W*:Y;*5<=>?%;< >?"A-B@DKEUG`HjJuKMNORSUVWXZ[.];^J`Uaabmd}efhjklmn*@AB*@*CD*CEF*GL+ HYIL*@JB*@+K+LddM*NYM*NN-O -P*Q*R*S*T,ç :,[>v w!y&z4{>|Q[cquy}(4< z*@UB*CD<*CE=*VW>*VX6l6l66*@hM6*@hM: %17<FU[esy?~*YL*ZM*@JB+*@+ [,R*,\N-]6-^6*@, [*@_Y`abcdbcebf ([. *.7=CO}*RF"*NL*@JB*@+g  [! *hL+iM,j},klN-Y:*-m:-n:*@op6*@JB*@KldL`[-q6-*@KLrç :  %2  %,2@Jek* w*VM,s>,W6,X6+t:u:lKh6lLh6 +v6 +]6 +^6 l h` h`6 l h`  h`6HY I: &2>DJPbtG**w_Y`+bxbf,y**wzN-|=}?69{&69:>Fy & *+*~  & *+* ~  & *+* ~  & *+*~  & *+*~   5, @.rFaunis/bin/client/ClientSettings.class0000664000175000017500000000461112063430422017035 0ustar useruser2 'CD &E &F &G &H &I &J &K 'L MN OP QR ST UV &WX YZ [\ C ] ^_ `a &bc &d e fgh ijk lmno classPathLjava/lang/String;clientDataPathplayerGraphicsPathimageFileEnding fieldWidthI fieldHeightdeltaLevelAmplitudehostport frameRate()VCodeLineNumberTable StackMapTablenX()Ljava/lang/String;()InumberOfDeltaLevelStatesdelayBetweenFrames checkPathsZ SourceFileClientSettings.java 45.png ,) -. /. 0. 1) 2. 3. pqr stu vwx yz{ |}~ ; ()java/lang/Exception 5 java/io/File 4java/lang/StringBuilder ; / ; clientData/ *)playerGraphics/ +) Player graphics directory  doesn't exist!  WARNING:  client/ClientSettingsjava/lang/ObjectgetClass()Ljava/lang/Class;java/lang/ClassgetProtectionDomain"()Ljava/security/ProtectionDomain;java/security/ProtectionDomain getCodeSource()Ljava/security/CodeSource;java/security/CodeSource getLocation()Ljava/net/URL; java/net/URLtoURI()Ljava/net/URI; java/net/URIgetPathprintStackTrace(Ljava/lang/String;)V getParentappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;toStringexists()Z isDirectoryjava/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintln!&' ()*)+),)-./.0.1)2.3. 456******** **  L+Y*LY+M*Y,*Y*-DG7J#  '!-%D*G'H(L)M,Y-p./08G9:+;6*73,;6*77-<6*7;/<6*7?0<6*7C=<6! *h`7G1;6*7K2<6*7O3<6* 7S><6! * l7W?;6SY*L+ + :Y!*"M#Y$,%,7[ \]6^O_Qa8 @6ABFaunis/bin/client/Client$2.class0000664000175000017500000000132112063430422015435 0ustar useruser2.       !$%this$0Lclient/Client;(Lclient/Client;)VCodeLineNumberTablerun()V SourceFile Client.javaEnclosingMethod& ' client/GameWindowFaunis ( )* +, -client/Client$2 InnerClassesjava/lang/Objectjava/lang/Runnable client/Clientinit&(Lclient/Client;IILjava/lang/String;)V access$0027(Lclient/Client;Lclient/GameWindow;)Lclient/GameWindow; access$000$(Lclient/Client;)Lclient/GameWindow;show   " *+*dF&*Y* W*fg%h#  Faunis/bin/client/Animateable.class0000664000175000017500000000045212063430422016277 0ustar useruser2hasEmote()ZgetEmote()Ljava/lang/String;setEmote(Ljava/lang/String;)V resetEmote()VgetFrame()IsetFrame(I)V SourceFileAnimateable.javaclient/Animateablejava/lang/Object   Faunis/bin/client/AnimationData.class0000664000175000017500000000056212063430423016611 0ustar useruser2   numberOfFramesIendType Lcommunication/enums/AniEndType;$(ILcommunication/enums/AniEndType;)VCodeLineNumberTable SourceFileAnimationData.java    client/AnimationDatajava/lang/Object()V!   3***,   Faunis/bin/client/MessageType.class0000664000175000017500000000165412063430423016331 0ustar useruser25 & '() * + , - . / 01errorLclient/MessageType;systemwhisper broadcast$VALUES[Lclient/MessageType;values()[Lclient/MessageType;CodeLineNumberTablevalueOf((Ljava/lang/String;)Lclient/MessageType;(Ljava/lang/String;I)V Signature()V&Ljava/lang/Enum; SourceFileMessageType.java  23client/MessageType 4      java/lang/Enumclone()Ljava/lang/Object;5(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;@1@@@@ "  # **+ !"!pTY Y  Y  YY SY SY SYS 4 #$%Faunis/bin/client/GraphWin.class0000664000175000017500000000576012063430422015623 0ustar useruser2 0b /c /d /e /fg h /i jk l /m n /o pq b /r s t u v wx yz { | } ~  l      / /    * DrawingPanel InnerClassesrepaintZwinLjavax/swing/JFrame; drawingPanelLclient/GraphWin$DrawingPanel;imgLjava/awt/image/BufferedImage;graphLjava/awt/Graphics;widthIheighttitleLjava/lang/String;(IILjava/lang/String;)VCodeLineNumberTableshow()VhidesetTitle(Ljava/lang/String;)VgetTitle()Ljava/lang/String;getWidth()I getHeightdrawmousePos()Ljava/awt/Point;setColor(Ljava/awt/Color;)V(III)VgetColor()Ljava/awt/Color;getRedgetGreengetBluecleardelay(J)V StackMapTable SourceFile GraphWin.java BG 34 => ?> @Aclient/GraphWin$DrawingPanel B 78 java/awt/image/BufferedImage BU 9: ;< javax/swing/JFrame 56 IJ Center KL R 3G STjava/awt/Color VW XN YN ZN MN ON  ]java/lang/InterruptedException could not delay! J Gclient/GraphWinjava/lang/Object(Lclient/GraphWin;)VsetIgnoreRepaint(Z)VcreateGraphics()Ljava/awt/Graphics2D;parentLclient/GraphWin;setDefaultCloseOperation(I)VsetSize(II)V setResizablegetContentPane()Ljava/awt/Container;java/awt/Containeradd<(Ljava/lang/String;Ljava/awt/Component;)Ljava/awt/Component; setVisiblegetMousePositionjava/awt/GraphicswhiteLjava/awt/Color;fillRect(IIII)Vjava/lang/Threadsleepjava/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintlnprintStackTrace!/03456789:;<=>?>@ABCD*****-*Y** * Y** ** ***Y****-**WEF$ &'()$*,+@,K.S/^0f1o2w345FGD% *E 89HGD% *E <=IJD% *+E @AKLD *ECMND*EFOND*EIPGQRD *EO3GD$*E RSSTD% *+E UVSUD6Y :*EX YZVWD *!E\XND# *!"E_YND# *!#EbZND# *!$Ee[GDT,*!L*%**&*'(*+Eijk#l+m \]DV)M+,-,.*Equrstv^G_ `a2 /1Faunis/bin/client/ColourBoneTranslator.class0000664000175000017500000000251012063430423020214 0ustar useruser2X +, - -. - / 01 2 3 04 5 06 7 08 9 0: ; 0< = 0> ? @AB colourToBoneLjava/util/HashMap; SignatureCLjava/util/HashMap;instanceLclient/ColourBoneTranslator; getInstance()Lclient/ColourBoneTranslator;CodeLineNumberTable StackMapTable()V translate0(Ljava/awt/Color;)Lcommunication/enums/BodyPart; SourceFileColourBoneTranslator.java client/ColourBoneTranslator %&java/util/HashMap C DE FG HI JE KG LE MG NE OG PE QG RE SG TE UG VWcommunication/enums/BodyPartjava/lang/Objectjava/awt/ColorMAGENTALjava/awt/Color;headLcommunication/enums/BodyPart;put8(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;ORANGEbodyGRAYtailGREENrightArmCYANleftArmREDrightLegBLUEleftLegget&(Ljava/lang/Object;)Ljava/lang/Object;!  !"= Y#!"#$%&"r**Y* W* W*  W* W* W* W* W#* '()*++9,G-U.c/q2'("$ *+#6)*Faunis/bin/client/Animator$AnimatingTask.class0000664000175000017500000000500212063430422020362 0ustar useruser2 !6 "7 8 !9 !: ; <= !>? 7 @ AB C D EF G H IJ EK LMN 7O P Q R STU SV AWX YZ[^$assertionsDisabledZthis$0Lclient/Animator;(Lclient/Animator;)VCodeLineNumberTablerun()V StackMapTable_`isAnimationFinished()Zanimate SourceFile Animator.java %& ', ab 01 2, cde fg #$java/lang/AssertionError h,i jk lm nop qo rs t$u wx ykz {|java/lang/StringBuilderIncrease frame from }~ }   to client/Animator 1client/Animator$AnimatingTask AnimatingTask InnerClassesjava/util/TimerTaskjava/lang/Objectjava/lang/Throwable animateableLclient/Animateable;parentLclient/AnimatorManager;client/AnimatorManagergetSynchroStuffForAnimatorStop()Ljava/lang/Object;stopAndUnregisterclient/AnimateablegetFrame()I maxFrameIndexIendType Lcommunication/enums/AniEndType;communication/enums/AniEndTyperevertrunningMutexKeyLjava/lang/Object; stopRunningclient/Animator$1)$SwitchMap$communication$enums$AniEndType[Iordinaljava/lang/SystemoutLjava/io/PrintStream;append-(Ljava/lang/String;)Ljava/lang/StringBuilder;(I)Ljava/lang/StringBuilder;toString()Ljava/lang/String;java/io/PrintStreamprint(Ljava/lang/String;)VprintlnsetFrame(I)Vjava/lang/ClassdesiredAssertionStatus!!"#$%&'()" *+**P+,),v*YL* *+ñ+çM+,*L+ Y +YM*YN* * -ç :-,ç :,  O_bbfbEknnrn*:U VWXZ"\/]A^E_O`Va]bicud-, .D/...D/D/01)Y)* <* **g h%i'j-'2,)*YL*YM*,+ñ* >*.llY* >Y*A* 6Y`*`,ç :,+ç :+ # "#*Nn opq#r0sXuqvtwxyz{~-" #..4((=D/D/3,)5 *P- @45]!\IFaunis/bin/client/GraphWin$DrawingPanel.class0000664000175000017500000000131012063430422020146 0ustar useruser2,       !$serialVersionUIDJ ConstantValueparentLclient/GraphWin;this$0(Lclient/GraphWin;)VCodeLineNumberTablepaintComponent(Ljava/awt/Graphics;)V SourceFile GraphWin.java  %  & '() *+client/GraphWin$DrawingPanel DrawingPanel InnerClassesjavax/swing/JPanel()Vclient/GraphWinimgLjava/awt/image/BufferedImage;java/awt/Graphics drawImage3(Ljava/awt/Image;IILjava/awt/image/ImageObserver;)Z!   " *+*x5*++**W}~# "Faunis/bin/client/PlayerGraphics.class0000664000175000017500000001270012063430422017011 0ustar useruser2 = ; ; ; ; ;  ;  ;  + ; ;             info%Lcommunication/GraphicalPlayerStatus;parentLclient/Client; deltaLevelIframe$assertionsDisabledZ7(Lcommunication/GraphicalPlayerStatus;Lclient/Client;)VCodeLineNumberTablegetBone-(Lcommunication/enums/BodyPart;)Lclient/Bone; StackMapTabledraw(Ljava/awt/Graphics;III)V drawRecursivee(Lcommunication/enums/BodyPart;Lcommunication/enums/BodyPart;IILjava/awt/Graphics;Ljava/util/List;I)V Signature(Lcommunication/enums/BodyPart;Lcommunication/enums/BodyPart;IILjava/awt/Graphics;Ljava/util/List;I)VgetType&()Lcommunication/enums/CharacterClass;getPath()Lcommunication/movement/Path;setPath (Lcommunication/movement/Path;)VgetX()IgetY resetPath()V resetEmote getDeltaLevel setDeltaLevel(I)VhasPath()ZgetName()Ljava/lang/String; getDirection!()Lcommunication/enums/Direction; setDirection"(Lcommunication/enums/Direction;)VgetEmotesetEmote(Ljava/lang/String;)VhasEmotegetFramesetFrame moveAbsolute(IIZ)V SourceFilePlayerGraphics.java Ih DE FE @A BC mnwalk stand  M  qr java/util/List GHjava/lang/AssertionError VW MN java/lang/StringBuilderCouldn't find bone for ! p w Couldn't find offset for , frame  n communication/enums/BodyPart  E E QR  Reset path.Set frame to 0. ERROR: setDirection(null) xn client/PlayerGraphics njava/lang/Objectcommunication/movement/Moveableclient/Animateablejava/lang/String$communication/GraphicsContentManager communication/enums/AniCompoType client/Bonejava/awt/Pointjava/util/Iterator#communication/GraphicalPlayerStatus currentEmoteLjava/lang/String; client/ClientgetGraphicsContentManager(()Lcommunication/GraphicsContentManager;type$Lcommunication/enums/CharacterClass; directionLcommunication/enums/Direction;(Lcommunication/enums/CharacterClass;Ljava/lang/String;Lcommunication/enums/BodyPart;Lcommunication/enums/Direction;)Lclient/Bone;getCompositionTypeH(Lcommunication/enums/CharacterClass;)Lcommunication/enums/AniCompoType;compact"Lcommunication/enums/AniCompoType;getCompactDrawingOrder()Ljava/util/List;getDrawingOrders()Ljava/util/HashMap;java/util/HashMapget&(Ljava/lang/Object;)Ljava/lang/Object;bodyLcommunication/enums/BodyPart;java/lang/SystemoutLjava/io/PrintStream;append-(Ljava/lang/String;)Ljava/lang/StringBuilder;-(Ljava/lang/Object;)Ljava/lang/StringBuilder;toStringjava/io/PrintStreamprintlngetConnectionOffset1(Lcommunication/enums/BodyPart;I)Ljava/awt/Point;(I)Ljava/lang/StringBuilder;iterator()Ljava/util/Iterator;hasNextnext()Ljava/lang/Object;getConnectionOffsets(I)Ljava/util/Set; java/util/SetxypathLcommunication/movement/Path;name!communication/movement/MovingTaskdeltaToDirection#(II)Lcommunication/enums/Direction;java/lang/ClassdesiredAssertionStatus!;=>?@ABCDEFEGHIJKE****+*,L/+ ,012MNK|@* M**M M* * ,+* L67 89";%<O  PQRK]* :* : :*: Y*+L"B CFG)I:LMM\OO)STUVWK*+:!Y+ !"#+$:  +Y%+ &'!"# Y(:  ) *+: ,-:  )p *+:  ,=  6 $:* + ..dd //dd + .d /d0eL>TU V*X4Y9Za\t_`abcghlO- *X6YZ#[ZU[\]^_K * Lo`aK *1LtbcK% *+1L yzdeK *2L~feK *3LghK:*1*4#L ihK:**5#L jeK*LklK"*L mnK *6LopK *7LqrK * LstKY'+ 8#+ Y*+ L &O upK *LvwK% *+L xnK *9LyeK*LzlK"*L {|Ks:(*2d*3d:: * *2*3L )19O)}hK5;<L(O @~Faunis/bin/client/Animator$1.class0000664000175000017500000000127112063430422015774 0ustar useruser2,      !)$SwitchMap$communication$enums$AniEndType[I()VCodeLineNumberTable StackMapTable SourceFile Animator.javaEnclosingMethod"# $% &' ()java/lang/NoSuchFieldError *' +'client/Animator$1 InnerClassesjava/lang/Objectclient/Animatorcommunication/enums/AniEndTypevalues#()[Lcommunication/enums/AniEndType;repeat Lcommunication/enums/AniEndType;ordinal()Irevertend    ~7 OKOKOK #&'25sWMM Faunis/bin/server/0000775000175000017500000000000012063430423013076 5ustar useruserFaunis/bin/server/MainServer.class0000664000175000017500000003635512063430424016215 0ustar useruser2W 9: 9 ; <=> ?@ABC 9 DE 9 FG 9 H I J KL 9M N O P Q R ST U V WXYZ $[ $\ $] $^_ ` a *b c *d ef 1gh 3i j kl mno :p 7qr 7st ?u vwx yz { | v}~ G9 v ?  N    N    : : : f[ f f f r q p v p p |  f f w N  N  } 7  w 7 7 7 7        7 } r[     N N f  @   v    ? 9  f  9serverSettingsLserver/ServerSettings; receptionLserver/Reception;butlersLjava/util/List; Signature!Ljava/util/List;accnameToButlerLjava/util/HashMap;6Ljava/util/HashMap;mapnameToMapman:Ljava/util/HashMap;activePlayernameToPlayer6Ljava/util/HashMap;loggedAccnameToAccount7Ljava/util/HashMap;graphicsContentManager&Lcommunication/GraphicsContentManager;allExistingPlayerNamesLjava/util/HashSet;'Ljava/util/HashSet;directoryFilterLjava/io/FileFilter;$assertionsDisabledZ()VCodeLineNumberTablemain([Ljava/lang/String;)Vrun StackMapTable:YfhgetServerSettings()Lserver/ServerSettings;getGraphicsContentManager(()Lcommunication/GraphicsContentManager; getMapman'(Ljava/lang/String;)Lserver/MapManager;getActivePlayerByName#(Ljava/lang/String;)Lserver/Player;getButlerByPlayerName#(Ljava/lang/String;)Lserver/Result;l4(Ljava/lang/String;)Lserver/Result;getMapmanByPlayerName8(Ljava/lang/String;)Lserver/Result; createButler"(Ljava/net/Socket;)Lserver/Butler;t deleteButler(Lserver/Butler;)V createAccount5(Ljava/lang/String;Ljava/lang/String;)Lserver/Result;J(Ljava/lang/String;Ljava/lang/String;)Lserver/Result; logoutAccount8(Ljava/lang/String;)Lserver/Result; loginAccountD(Lserver/Butler;Ljava/lang/String;Ljava/lang/String;)Lserver/Result;oV(Lserver/Butler;Ljava/lang/String;Ljava/lang/String;)Lserver/Result;loggedIn(Ljava/lang/String;)ZexistAccountSubdir loadAccountEG(Ljava/lang/String;Ljava/lang/String;)Lserver/Result;createNewPlayerW(Lserver/Account;Ljava/lang/String;Lcommunication/enums/CharacterClass;)Lserver/Result;l(Lserver/Account;Ljava/lang/String;Lcommunication/enums/CharacterClass;)Lserver/Result; savePlayer(Lserver/Player;)ZloadAndActivatePlayer3(Lserver/Account;Ljava/lang/String;)Lserver/Result;D(Lserver/Account;Ljava/lang/String;)Lserver/Result; unloadPlayer(Lserver/Player;)VcreateAccountSubdir(Lserver/Account;)ZplayerDirString8(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;existPlayerDir'(Ljava/lang/String;Ljava/lang/String;)ZcreatePlayerDir'(Ljava/lang/String;Ljava/lang/String;)V shutdownAllloadAllExistingPlayerNames()Ljava/util/HashSet;)()Ljava/util/HashSet; SourceFileMainServer.java server/MainServer  Welcome to the Faunis server! (Copyright 2012 Simon Ley alias "skarute"#Licensed under GNU AGPL v3 or laterserver/ServerSettings java/util/ArrayList java/util/HashMap java/lang/StringBuilderaccount storage in     23 server/Reception   Reception has been created.javax/swing/JFrame MainServer      $communication/GraphicsContentManager     /  communication/Map server/MapManager    server/Player =getButlerByPlayerName(): Player with given name isn't active! server/Result  =getMapmanByPlayerName(): Player with given name isn't active!  server/Butler  new butler for client at port    java/lang/AssertionError  Butler at port !" destroyed! server/Account # ()Account  successfully created.$ %&Account couldn't be created!?Account name already exists! "This account isn't even logged in! '(3Can't log out since there's still an active player! )   successfully logged out.%Login to non-existent account failed!"This account is already logged in!  *+ ,- successfully logged in.#There were errors while logging in . . java/io/File/ Check if / exists... 0+ 1+, couldn't be loaded since it does not exist! /account.txtjava/io/BufferedReaderjava/io/InputStreamReaderjava/io/FileInputStream 2 3 4java/io/FileNotFoundExceptionCouldn't find account.txt for 5!Error while reading account data! 6 7java/io/IOException 8Password invalid, since  != Invalid login data! /players/ 9: ; successfully loaded. < => ?You cannot exceed the limit of  players per account!A player with the name  already exists! @  The player could not be created! /A:WARNING: MainServer.savePlayer(): Player was still moving! B C *+ ,- ./java/io/FileOutputStreamjava/io/ObjectOutputStream D EF GH&MainServer: Player successfully saved.Couldn't load + since there's still another player active!+ since a player of that name doesn't exist!java/io/ObjectInputStream I- java/lang/ClassNotFoundException J' K/players L+java/io/PrintWriter M NO P+ Q--server/mapmanToButlerOrders/MBStopThreadOrder R Sjava/util/HashSet 9TERROR: Couldn't add U V+server/MainServer$1 InnerClassesjava/lang/Objectjava/lang/Stringjava/lang/Throwablejava/net/Socket[Ljava/io/File;"communication/enums/CharacterClasscommunication/movement/Pathjava/util/Iteratorjava/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintln(Ljava/lang/String;)Vappend-(Ljava/lang/String;)Ljava/lang/StringBuilder; accountPath()Ljava/lang/String;toString checkPaths receptionPort()I(Lserver/MainServer;I)VsetSize(II)VsetDefaultCloseOperation(I)V setVisible(Z)VplayerGraphicsPathimageFileEndingloadResourcesForServer starterRegion(Ljava/lang/String;II)V)(Lserver/MainServer;Lcommunication/Map;)Vput8(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;get&(Ljava/lang/Object;)Ljava/lang/Object;'(Ljava/lang/Object;Ljava/lang/String;)VgetAccountName getMapName'(Lserver/MainServer;Ljava/net/Socket;)Vjava/util/Listadd(Ljava/lang/Object;)ZgetPort(I)Ljava/lang/StringBuilder;containsremovegetClientSocket()Ljava/net/Socket;<(Ljava/lang/String;Ljava/lang/String;Ljava/util/ArrayList;)Vjava/lang/BooleanvalueOf(Z)Ljava/lang/Boolean;getActivePlayer()Lserver/Player; containsKey successful()Z getResult()Ljava/lang/Object;getErrorMessagegetPathexists isDirectory(Ljava/io/File;)V(Ljava/io/InputStream;)V(Ljava/io/Reader;)VprintStackTracereadLinecloseequals listFiles()[Ljava/io/File;getNamemaxPlayersPerAccountgetPlayerNames()Ljava/util/ArrayList;size](Ljava/lang/String;Lcommunication/enums/CharacterClass;Ljava/lang/String;Ljava/lang/String;)V()Lcommunication/movement/Path; resetPath resetEmote(Ljava/io/OutputStream;)V writeObject(Ljava/lang/Object;)VsetPath (Lcommunication/movement/Path;)V readObjectsetActivePlayer getPasswordmkdirshutdowniterator()Ljava/util/Iterator;hasNextnext(Lserver/MapManager;)V((Lserver/mapmanToButlerOrders/MBOrder;)V%(Ljava/io/FileFilter;)[Ljava/io/File;java/lang/ClassdesiredAssertionStatus! *0 - YL+CD E# * Y * Y*Y*Y*Y*YY* * ***Y** !"#$Y%&L+ȶ'+(+)**Y* +* ,-.*./* 0M1Y,222N3Y*-4:*Y:*,5Wç : nHIJK#L.M9NDOOPZQySUVXZ[\]`bfghi jk"l!* o*.se*YM*+63,ðN,-yz{e*YM*+67,ðN,-@*+8M,9N:Y-;,N*Y:»:Y*-6;ð:$788=8" $8! F?Y*+@M*YN*,AW-ç :-YB+CD,!!%! (D!\*YM²E*+F GYH*+IW,çN,-YJ+KCDL/2252"-7["Ol*+MZNY+, YON*-P6.YQ+R:YS;T::Y;UN:Y-;*  %CPT_b P*+VWM:Y,;*YN*+6NM-ç :-,XN-Y::Y;*Y:*Y:²E*+Z GYHE*+Z GYH*+[W*+[Wç :ç :YQ+\:YS;*--1-\TR (49=ALT\uE (WE    *,M]::Y;*,V^::Y;*,-_:`aN:*Y:*Y:²E*,Z GYHE*,Z GYH*,5W*,+5Wç :ç :  YQ,b:Y;Yc,d:Ye;XPV #.6>HPXq   5 B ZE( q*YM*+Z,ì,ìN,- CZfYY* +ghMYi,jk,l,m%F X@*+M&YQ+nN:Y-;* NfYY-+oh:pYqYrYstu:.:Yw+x:Yy;z:{:y}:Yy;,~1Y,:Y;fYY-+h:: Y: :  6 6     2:   W NY+, O: YQ+:Y ;Slov|z()!*+,3.S1l6o2q3459:?;<=>ABCLM!N*ODPOOUSbTUZ+C*N6; F* 0:*Y:+Y:+:* 6 +:   /Y D: :Y ;ð*,.Y,: :Y ;ð7Y,-:*6  & ,W*,W:YS;ð: :Y ;ð:  : ]a`aZ\ ^_ab%c+d5ePfahlijlmnopqstvwa 5>  +YM+N- +++<:+:E*M GYH*:* *fYYgh:Y:Y:  + :  }+-,ì+-,ç : , |f}~ #)@JU][*E ! "#2 !+X&Y,N:Y-;+,&Y,N:Y-;E*+, GYH:rYY*+,g,NY-:7::} :E GYH+Y:+ç :*Y:*,5Wç ::Y;u|u j *5NXru_ *-EI$%&' x*YN+Y:*+W+!(Lserver/Butler;Lserver/Butler;)VCodeLineNumberTablerun()V StackMapTable)%& SourceFile Butler.java   . /0 123 45#server/mapmanToButlerOrders/MBOrderjava/lang/InterruptedException 6 78server/Butler$ServerRunnableServerRunnable InnerClassesjava/lang/Objectjava/lang/Runnable server/Butler stopRunningZ serverOrders$Ljava/util/concurrent/BlockingQueue;"java/util/concurrent/BlockingQueuetake()Ljava/lang/Object;printStackTracehandleServerOrder((Lserver/mapmanToButlerOrders/MBOrder;)V  /*+**,k lm4*,L*LM, +*+ б & r s uxv w$y(z3|+  *Faunis/bin/server/Account.class0000664000175000017500000000206412063430423015523 0ustar useruser2* " # $ % &'(nameLjava/lang/String;password playerNamesLjava/util/ArrayList; Signature)Ljava/util/ArrayList; activePlayerLserver/Player;<(Ljava/lang/String;Ljava/lang/String;Ljava/util/ArrayList;)VCodeLineNumberTableP(Ljava/lang/String;Ljava/lang/String;Ljava/util/ArrayList;)VgetName()Ljava/lang/String; getPasswordgetPlayerNames()Ljava/util/ArrayList;+()Ljava/util/ArrayList;getActivePlayer()Lserver/Player;setActivePlayer(Lserver/Player;)V SourceFile Account.java )  server/Accountjava/lang/Object()V!    E**+*,*-* !"#$ *)*-*1 *5"*+ 9: !Faunis/bin/server/MapManager$MapManRunnable.class0000664000175000017500000000165112063430423020765 0ustar useruser25     !"#$ % &'*+myMapmanLserver/MapManager;this$0)(Lserver/MapManager;Lserver/MapManager;)VCodeLineNumberTablerun()V StackMapTable'#$ SourceFileMapManager.java   , -./ 01#server/butlerToMapmanOrders/BMOrderjava/lang/InterruptedException 2 34 server/MapManager$MapManRunnableMapManRunnable InnerClassesjava/lang/Objectjava/lang/Runnableserver/MapManagerorders$Ljava/util/concurrent/BlockingQueue;"java/util/concurrent/BlockingQueuetake()Ljava/lang/Object;printStackTracehandleButlerOrder((Lserver/butlerToMapmanOrders/BMOrder;)V   /*+**,i jk{)L*LM,+*+ qsvtuwx)  (Faunis/bin/server/Result.class0000664000175000017500000000135212063430423015404 0ustar useruser2"    resultLjava/lang/Object; SignatureTT; errorMessageLjava/lang/String;'(Ljava/lang/Object;Ljava/lang/String;)VCodeLineNumberTable(TT;Ljava/lang/String;)V getResult()Ljava/lang/Object;()TT;getErrorMessage()Ljava/lang/String; successful()Z StackMapTable(Ljava/lang/Object; SourceFile Result.java !   server/Resultjava/lang/Object()V!   3**+*, !*$*(0 *, @Faunis/bin/server/MainServer$1.class0000664000175000017500000000066212063430424016332 0ustar useruser2  ()VCodeLineNumberTableaccept(Ljava/io/File;)Z SourceFileMainServer.javaEnclosingMethod  server/MainServer$1 InnerClassesjava/lang/Objectjava/io/FileFilterserver/MainServer java/io/File isDirectory()Z0* ; + >   Faunis/bin/server/Butler$ClientRunnable.class0000664000175000017500000000237112063430423020257 0ustar useruser2O $ % & '( ') *+, -./ 01 '23 45 '67:;myButlerLserver/Butler;this$0!(Lserver/Butler;Lserver/Butler;)VCodeLineNumberTablerun()V StackMapTable7:,,3 SourceFile Butler.java   < => ?@A BCjava/io/IOExceptionD EFconnection reset!!G HI JK java/lang/ClassNotFoundException L*communication/clientToButlerOrders/CBOrder MNserver/Butler$ClientRunnableClientRunnable InnerClassesjava/lang/Objectjava/lang/Runnable server/Butler stopRunningZ clientInputLjava/io/ObjectInputStream;java/io/ObjectInputStream readObject()Ljava/lang/Object;java/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintln(Ljava/lang/String;)Vshutdown()ZprintStackTracehandleClientOrder/(Lcommunication/clientToButlerOrders/CBOrder;)V /*+**, U*ML*L$M * * WM, ++*+  6 ># $ &/')#*-+5,6-7.;0F2Q4T5. !"#9 '8Faunis/bin/server/Player.class0000664000175000017500000000523712063430423015370 0ustar useruser2q U V W X Y Z[ \ ] ^ _` U V W \ ab _ c c ] ^ defghiserialVersionUIDJ ConstantValuenameLjava/lang/String;type$Lcommunication/enums/CharacterClass;currentMapName accountNamexIy directionLcommunication/enums/Direction;pathLcommunication/movement/Path; currentEmote](Ljava/lang/String;Lcommunication/enums/CharacterClass;Ljava/lang/String;Ljava/lang/String;)VCodeLineNumberTablegetGraphicalPlayerStatus'()Lcommunication/GraphicalPlayerStatus; StackMapTablef``j getMapName()Ljava/lang/String;getType&()Lcommunication/enums/CharacterClass;getAccountNamesetAccountName(Ljava/lang/String;)VgetNamegetX()IgetYgetPath()Lcommunication/movement/Path;setPath (Lcommunication/movement/Path;)V resetPath()VhasPath()ZgetCurrentEmotesetCurrentEmote resetEmote isAnimating moveAbsolute(IIZ)V setMapName SourceFile Player.java .I ! "# $! %!k l* )* &' (' +,#communication/GraphicalPlayerStatusj mE -!n op server/Playerjava/lang/Objectjava/io/Serializablecommunication/movement/Moveablecommunication/movement/Pathcommunication/enums/Directiondowncopy!communication/movement/MovingTaskdeltaToDirection#(II)Lcommunication/enums/Direction;!  !"#$!%!&'(')*+,-!./0l0**+*,*-**** * 1* -. /012 3%4*5/6230P Y L+* +*+*+*  * +*+*+* +1& =>?@ A6B>CFDNE4%,56756789:0*1K;<0*1N=:0*1Q>?0"*+1 TU@:0*1WAB0*1ZCB0* 1]DE0* 1`FG0"*+ 1 cdHI0"* 1 fgJK00 * 1i4 @L:0*1lM?0"*+1 opNI0"*1 rsOK00 *1u4 @PQ0d+*d* d: *** 1yz|} %*4 R?0"*+1 STFaunis/bin/server/Butler.class0000664000175000017500000003123312063430423015364 0ustar useruser24   ! " # $ %& ' ( )*+ ,-. /0 1 23 /4 5 67 89:; < => ? @ AB !< C D EF G HIJ K LM NOP .Q NR STU 2V W X YZ [ L\ ]^ ]_ ]`a >b cd A e Lf gh ij Fk lm Jn Jop Jqr Ps tuv Ss w x Ly iz{ z| z} L~  ]| L i t[  L g i  >| k  n        L  V N 8        _             V ServerRunnable InnerClassesClientRunnableshutdownMutexKeyLjava/lang/Object;shutdownOccupiedZparentLserver/MainServer; clientSocketLjava/net/Socket; clientInputLjava/io/ObjectInputStream; clientOutputLjava/io/ObjectOutputStream; clientThreadLjava/lang/Thread;clientRunnableLserver/Butler$ClientRunnable; stopRunning loggedAccountLserver/Account; activePlayerLserver/Player; activeMapmanLserver/MapManager; serverOrders$Ljava/util/concurrent/BlockingQueue; SignatureKLjava/util/concurrent/BlockingQueue; serverThreadserverRunnableLserver/Butler$ServerRunnable;$assertionsDisabled'(Lserver/MainServer;Ljava/net/Socket;)VCodeLineNumberTable StackMapTable7assertActivePlayer()ZassertLoggedAccountshutdown!loadActivePlayer9(Lcommunication/clientToButlerOrders/CBLoadPlayerOrder;)VaddPlayerToMapman(Lserver/MapManager;Z)VremovePlayerFromMapmanunloadActivePlayer()V loginAccount4(Lcommunication/clientToButlerOrders/CBLoginOrder;)V logoutAccountcreateNewPlayer;(Lcommunication/clientToButlerOrders/CBCreatePlayerOrder;)VmoveChar3(Lcommunication/clientToButlerOrders/CBMoveOrder;)V disconnectforwardChatOrder3(Lcommunication/clientToButlerOrders/CBChatOrder;)VforwardEmoteOrder;(Lcommunication/clientToButlerOrders/CBTriggerEmoteOrder;)VgetClientSocket()Ljava/net/Socket;handleClientOrder/(Lcommunication/clientToButlerOrders/CBOrder;)Vput((Lserver/mapmanToButlerOrders/MBOrder;)VhandleServerOrdersendOrderToClient/(Lcommunication/butlerToClientOrders/BCOrder;)VclientChatMessage3(Lserver/mapmanToButlerOrders/MBChatMessageOrder;)V clientAddChar/(Lserver/mapmanToButlerOrders/MBAddCharOrder;)VclientChangeChar2(Lserver/mapmanToButlerOrders/MBChangeCharOrder;)VclientRemoveChar2(Lserver/mapmanToButlerOrders/MBRemoveCharOrder;)V clientMapInfo/(Lserver/mapmanToButlerOrders/MBMapInfoOrder;)V changeMapman9(Lserver/mapmanToButlerOrders/MBCharAtOtherMapmanOrder;)VsendErrorMessage(Ljava/lang/String;)V SourceFile Butler.java java/lang/Object 'java/util/concurrent/ArrayBlockingQueue   /Butler: Try to create input / output streams... java/io/ObjectOutputStream   java/io/ObjectInputStream   java/io/IOException &Couldn't create input / output stream!+Input and output streams have been created.server/Butler$ClientRunnable  java/lang/Thread  server/Butler$ServerRunnable Command requires loaded player!   Command requires logged account!Butler: Initiate shutdown...   -server/mapmanToButlerOrders/MBStopThreadOrder   java/lang/RuntimeExceptionCouldn't choke clientThread!    9Butler: Couldn't load player: There's already one loaded.      server/Player  java/lang/AssertionError  9communication/butlerToClientOrders/BCSetClientStatusOrder      java/lang/StringBuilderButler: Player    successfully loaded. +server/butlerToMapmanOrders/BMRegisterOrder  -server/butlerToMapmanOrders/BMUnregisterOrder   Butler: Unloaded player.   server/AccountDButler: Couldn't log in since account seems to be already logged in.   0A8CJD\H_E`FdGlItLMNPQRS_ >*% *&'VW XZ>*( *)']^ _av*YL*+ì*+çM+, * *(*+**,** -* .Y/0W*1L+2Y345**$645*$*6*$6*6* ]dgbstuwx"y*|1}5~=BK]dghlv Iq 1*7*% *8'+9M**(,:N-; *-<'*-=>%*%?:@ AYB@*C AYB**DC**CE*FYGHI JYKLM,MNMO N(/78CL_t !&g9@*% AYB@+ AYB+PY**%QR'8g9@*% AYB@+ AYB+SY**%TR'8Z*7*U@*C AYB**CV**%W*%*C*FYXHI Y * %.9>CQYM*(B**+Z+[\M,;*,=](*FYXHI *,<' *^'& *;CFL ;N*(C*%*_**(`aL+; *+<'*(*FYbHI *c'2 !(016DGM b+*7**(+defM,; *,<'"* !S%*7*U*CgY*%*+hR$D*FYiHI**jW I *U*CkY*+*%lmR  I *U*CnY**%+opR*+q r *s+t u *+tv+w x *+wy+z { *+z|+} ~ *++  *++  *_m+  *+S+  *+9+2  *YJYKM*MOI~9:;<=%>0?7@?AJBQCYDdEkFsGzHIJKLMNOPQRSTUVY 5^* +M,2Y4 ` d abceM  %++*C  +*++*+s+*+a+*+O+*+=+*+++.**jW+*+'R"-4?FQXcju|   I@* AYB*YM+  *+ N  ,ç :,(03>AAEA*  (034<HJD b-+M, ,>*Y++I, @) *Y+I  ) *Y+I  ) *Y+I  0*Y+*%lI y7+M@*C, AYB+N*C*,V*-E*-C" %+16) *Y+I  5@' @!Faunis/bin/server/mapmanToButlerOrders/0000775000175000017500000000000012063430423017207 5ustar useruserFaunis/bin/server/mapmanToButlerOrders/MBAddCharOrder.class0000664000175000017500000000124712063430423022743 0ustar useruser2    playerNameLjava/lang/String; graphStatus%Lcommunication/GraphicalPlayerStatus;M(Lserver/MapManager;Ljava/lang/String;Lcommunication/GraphicalPlayerStatus;)VCodeLineNumberTable getPlayerName()Ljava/lang/String;getGraphStatus'()Lcommunication/GraphicalPlayerStatus; SourceFileMBAddCharOrder.java    *server/mapmanToButlerOrders/MBAddCharOrder#server/mapmanToButlerOrders/MBOrder(Lserver/MapManager;)V!   4*+*,*-  ! "# * ' * +Faunis/bin/server/mapmanToButlerOrders/MBStopThreadOrder.class0000664000175000017500000000042712063430423023531 0ustar useruser2    (Lserver/MapManager;)VCodeLineNumberTable SourceFileMBStopThreadOrder.java -server/mapmanToButlerOrders/MBStopThreadOrder#server/mapmanToButlerOrders/MBOrder!"*+  Faunis/bin/server/mapmanToButlerOrders/MBChatMessageOrder.class0000664000175000017500000000171512063430423023641 0ustar useruser2'        !"fromPlayernameLjava/lang/String; toPlayernamemessageL(Lserver/MapManager;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)VCodeLineNumberTableF(Lserver/MapManager;Lserver/butlerToMapmanOrders/BMChatMessageOrder;)VgetFromPlayername()Ljava/lang/String;getToPlayername getMessage SourceFileMBChatMessageOrder.java # $ % & .server/mapmanToButlerOrders/MBChatMessageOrder#server/mapmanToButlerOrders/MBOrder(Lserver/MapManager;)V.server/butlerToMapmanOrders/BMChatMessageOrder getFromName getToName!    >*+*,*-* !"F*+*,*,*,%& '()*,*0*4Faunis/bin/server/mapmanToButlerOrders/MBRemoveCharOrder.class0000664000175000017500000000072112063430423023504 0ustar useruser2   playerNameLjava/lang/String;((Lserver/MapManager;Ljava/lang/String;)VCodeLineNumberTable getPlayerName()Ljava/lang/String; SourceFileMBRemoveCharOrder.java  -server/mapmanToButlerOrders/MBRemoveCharOrder#server/mapmanToButlerOrders/MBOrder(Lserver/MapManager;)V! + *+*,    *   Faunis/bin/server/mapmanToButlerOrders/MBCharAtOtherMapmanOrder.class0000664000175000017500000000074012063430423024750 0ustar useruser2   newMapmanLserver/MapManager;)(Lserver/MapManager;Lserver/MapManager;)VCodeLineNumberTable getNewMapman()Lserver/MapManager; SourceFileMBCharAtOtherMapmanOrder.java  4server/mapmanToButlerOrders/MBCharAtOtherMapmanOrder#server/mapmanToButlerOrders/MBOrder(Lserver/MapManager;)V! + *+*,  !  * $ Faunis/bin/server/mapmanToButlerOrders/MBErrorMessageOrder.class0000664000175000017500000000073112063430423024050 0ustar useruser2   errorMessageLjava/lang/String;((Lserver/MapManager;Ljava/lang/String;)VCodeLineNumberTablegetErrorMessage()Ljava/lang/String; SourceFileMBErrorMessageOrder.java  /server/mapmanToButlerOrders/MBErrorMessageOrder#server/mapmanToButlerOrders/MBOrder(Lserver/MapManager;)V! + *+*,    *   Faunis/bin/server/mapmanToButlerOrders/MBOrder.class0000664000175000017500000000057612063430423021540 0ustar useruser2  sourceLserver/MapManager;(Lserver/MapManager;)VCodeLineNumberTable getSource()Lserver/MapManager; SourceFile MBOrder.java  #server/mapmanToButlerOrders/MBOrderjava/lang/Object()V! * **+    *  Faunis/bin/server/mapmanToButlerOrders/MBMapInfoOrder.class0000664000175000017500000000072412063430423023005 0ustar useruser2  mapInfoLcommunication/MapInfo;-(Lserver/MapManager;Lcommunication/MapInfo;)VCodeLineNumberTable getMapInfo()Lcommunication/MapInfo; SourceFileMBMapInfoOrder.java  *server/mapmanToButlerOrders/MBMapInfoOrder#server/mapmanToButlerOrders/MBOrder(Lserver/MapManager;)V! + *+*,    * ! Faunis/bin/server/mapmanToButlerOrders/MBChangeCharOrder.class0000664000175000017500000000125512063430423023437 0ustar useruser2    playerNameLjava/lang/String; graphStatus%Lcommunication/GraphicalPlayerStatus;M(Lserver/MapManager;Ljava/lang/String;Lcommunication/GraphicalPlayerStatus;)VCodeLineNumberTable getPlayerName()Ljava/lang/String;getGraphStatus'()Lcommunication/GraphicalPlayerStatus; SourceFileMBChangeCharOrder.java    -server/mapmanToButlerOrders/MBChangeCharOrder#server/mapmanToButlerOrders/MBOrder(Lserver/MapManager;)V!   4*+*,*-  ! * $ * (Faunis/bin/server/MapManager.class0000664000175000017500000002561712063430423016150 0ustar useruser2                        ' P       2  2      2 >    ! " # $%  & ' ( ) *+ ,- ,./0 Q1 234 56 078 W9 : ;<= 0 ;> . ? @ .A B .C D EF G HI jJ K L  * * M *N O PQ u1 , ,RS y T +U }VW XYZMapManRunnable InnerClassesparentLserver/MainServer;mapLcommunication/Map;threadLjava/lang/Thread;runnableLjava/lang/Runnable;orders$Ljava/util/concurrent/BlockingQueue; SignatureKLjava/util/concurrent/BlockingQueue;registeredPlayersLjava/util/HashMap;3Ljava/util/HashMap;playerNameToPlayer6Ljava/util/HashMap; movingPlayersBLjava/util/HashMap;$assertionsDisabledZ)(Lserver/MainServer;Lcommunication/Map;)VCodeLineNumberTabletryStopMovement(Lserver/Player;)V StackMapTable[getSynchroStuffForMoverStop()[Ljava/lang/Object;unregisterMover$(Lcommunication/movement/Moveable;)VW\put((Lserver/butlerToMapmanOrders/BMOrder;)VgetMap()Lcommunication/Map; getMapName()Ljava/lang/String;handleButlerOrderbMTriggerEmoteOrder4(Lserver/butlerToMapmanOrders/BMTriggerEmoteOrder;)V]^_`ab fireEmote$(Lserver/Player;Ljava/lang/String;)V deleteEmote storeEmotenotifyAllCharChanged:(Ljava/lang/String;Lcommunication/GraphicalPlayerStatus;)VcbMChatMessageOrder3(Lserver/butlerToMapmanOrders/BMChatMessageOrder;)V/d movePlayer,(Lserver/butlerToMapmanOrders/BMMoveOrder;)VeregisterPlayer0(Lserver/butlerToMapmanOrders/BMRegisterOrder;)VUunregisterPlayer2(Lserver/butlerToMapmanOrders/BMUnregisterOrder;)V getMapInfo()Lcommunication/MapInfo;()V SourceFileMapManager.java java/util/HashMap 'java/util/concurrent/ArrayBlockingQueue f  server/MapManager$MapManRunnable g java/lang/Thread h i jkcommunication/movement/Mover l java/lang/Object  server/Playerjava/lang/AssertionError mkn ojava/lang/InterruptedException pjava/lang/RuntimeException&Couldn't pass the order to the mapman! qr s*server/butlerToMapmanOrders/BMMapInfoOrder t uv*server/mapmanToButlerOrders/MBMapInfoOrder w x+server/butlerToMapmanOrders/BMRegisterOrder -server/butlerToMapmanOrders/BMUnregisterOrder 'server/butlerToMapmanOrders/BMMoveOrder .server/butlerToMapmanOrders/BMChatMessageOrder /server/butlerToMapmanOrders/BMTriggerEmoteOrder yz {| }^ ~  _ ` /server/mapmanToButlerOrders/MBErrorMessageOrderEmote is invalid!  a b  e   q  c   server/Butler-server/mapmanToButlerOrders/MBChangeCharOrder  Mapman forwards chat message q .server/mapmanToButlerOrders/MBChatMessageOrder  d )Couldn't deliver message to given player.         &communication/movement/RoughMovingTask      q*server/mapmanToButlerOrders/MBAddCharOrder -server/mapmanToButlerOrders/MBRemoveCharOrder communication/MapInfo server/MapManager #communication/movement/MoverManagerjava/lang/Throwablecommunication/movement/Moveable"communication/enums/CharacterClassjava/lang/String$communication/GraphicsContentManager java/util/Setclient/AnimationDatacommunication/enums/AniEndTypejava/util/Iterator server/Result#communication/GraphicalPlayerStatus(I)V)(Lserver/MapManager;Lserver/MapManager;)V(Ljava/lang/Runnable;)Vstartget&(Ljava/lang/Object;)Ljava/lang/Object;stopremove"java/util/concurrent/BlockingQueue(Ljava/lang/Object;)VprintStackTrace(Ljava/lang/String;)Vcommunication/MapgetName#server/butlerToMapmanOrders/BMOrder getSource()Lserver/Butler;-(Lserver/MapManager;Lcommunication/MapInfo;)V((Lserver/mapmanToButlerOrders/MBOrder;)V getPlayer()Lserver/Player;getType&()Lcommunication/enums/CharacterClass;getEmoteequals(Ljava/lang/Object;)Zserver/MainServergetGraphicsContentManager(()Lcommunication/GraphicsContentManager;getAvailableAnimations5(Lcommunication/enums/CharacterClass;)Ljava/util/Set;contains((Lserver/MapManager;Ljava/lang/String;)VgetAnimationDataN(Lcommunication/enums/CharacterClass;Ljava/lang/String;)Lclient/AnimationData;endType Lcommunication/enums/AniEndType;revertgetGraphicalPlayerStatus'()Lcommunication/GraphicalPlayerStatus; currentEmoteLjava/lang/String;getCurrentEmotesetCurrentEmotevalues()Ljava/util/Collection;java/util/Collectioniterator()Ljava/util/Iterator;hasNext()Znext()Ljava/lang/Object;M(Lserver/MapManager;Ljava/lang/String;Lcommunication/GraphicalPlayerStatus;)Vjava/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintln getToNameF(Lserver/MapManager;Lserver/butlerToMapmanOrders/BMChatMessageOrder;)VgetButlerByPlayerName#(Ljava/lang/String;)Lserver/Result; successful getResult containsKey getXTarget()IgetX getYTargetgetY"communication/movement/PathFactorycreateAirlinePath#(IIII)Lcommunication/movement/Path;setPath (Lcommunication/movement/Path;)VJ(Lcommunication/movement/MoverManager;Lcommunication/movement/Moveable;J)VB(Lcommunication/movement/Mover;Lcommunication/movement/Moveable;)V setMovingTask&(Lcommunication/movement/MovingTask;)V8(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;hasPathgetAddPlayerMapEntry setMapNamegetRemovePlayerMapEntrykeySet()Ljava/util/Set;((Ljava/lang/String;Ljava/util/HashMap;)Vjava/lang/ClassdesiredAssertionStatus! `**+*,*Y*Y*Y* Y2 * Y** *Y**. 89 :;<$=/><?I@XA_B@*YM+YN*+: *+-ç :-,ç :, ),,0,588<8& EF GHI"J'M3N?O'DD$ Y*SR7+ Y+M*YN*,W-ç :-!,//3/WXY!Z*[6]^* +M, Y!" a e bcdfM*i *#m+ Y+$*%M+&'Y*,()Z+**+*+H+,*+,-6+.*+./$+0*+01+2 *+23Bqrst.u1v8wCxJyUz\{g|n}y~  +4M,5N+6: 78 *,9*::-;:<+=>Y*?@)-A: YB:C *,D *,EJ $%.6BST^qx%.=*YN+Y:+F:,G*+HIç :-ç :- %((-(25595" "0<%(D<*YM+YN+J+K*+H+FI-ç :-,ç :, %((,(14484" #/;#DD8*YN+Y:+,K*+H+FIç :-ç :- ##(#-0040 +7%#DJ*YN*LM:N!OP:QY*+,R)-ç :-?BBFB+=I'D. STU+VM, ,78L*YN*LM:N OP:WY*+X)-ç :-*Y:*,Nç :-7*Y:*-P:ç :WY*+X)C*,Y:Z[:+\>Y*@)]P:WY+X)!X[[_[kz}}}f !EVbckw &D'^ + Y+^M*YN²*,_ Y-ç :-*,`*,9+a,b+c,d,Y:,b,d+a+ce:,f,HN,F:ç :*Y:»Y*,gi:jY,k:l*,mWç :*Y:*-Iç :  n9<<@<ij7CHMcdi~    $D 09{ V+ Y*YM*YN+o:H:+p:Y:²q Yç :*_ Y*mW*_ Y*mW+r9Y:²s Y*#tç :  *%:'Y*()*LM:N-OP:   uY*Fv)-ç : - ,ç : , 9RUUZU ?BBFBKNNRNj & -!3"9#O$]%w&'()*+,-0134&5=9I:U;c<E%.Q"0DD + Y*YM*YN+w:H:*_ Y*`*9*W*_ Y*W+x3Y:²s Ytç :*LM:N!OP:yY*z)-ç :-,ç : ,  V>?@ A&B-CGEMGSI]JwKLMNOPSTVWXA 4/,K 'DDbYL*YM*{|N-N$-O:F:+HmW,ç :,}Y*#+~HKKOK"[\]0^7_C`FaRb)D5. @  Faunis/bin/server/butlerToMapmanOrders/0000775000175000017500000000000012063430423017207 5ustar useruserFaunis/bin/server/butlerToMapmanOrders/BMUnregisterOrder.class0000664000175000017500000000107212063430423023600 0ustar useruser2   playerLserver/Player;removePlayerMapEntryZ"(Lserver/Butler;Lserver/Player;Z)VCodeLineNumberTable getPlayer()Lserver/Player;getRemovePlayerMapEntry()Z SourceFileBMUnregisterOrder.java    -server/butlerToMapmanOrders/BMUnregisterOrder#server/butlerToMapmanOrders/BMOrder(Lserver/Butler;)V!   4*+*,*    * # * 'Faunis/bin/server/butlerToMapmanOrders/BMTriggerEmoteOrder.class0000664000175000017500000000112312063430423024043 0ustar useruser2   playerLserver/Player;emoteLjava/lang/String;3(Lserver/Butler;Lserver/Player;Ljava/lang/String;)VCodeLineNumberTable getPlayer()Lserver/Player;getEmote()Ljava/lang/String; SourceFileBMTriggerEmoteOrder.java    /server/butlerToMapmanOrders/BMTriggerEmoteOrder#server/butlerToMapmanOrders/BMOrder(Lserver/Butler;)V!   4*+*,*-   * " * &Faunis/bin/server/butlerToMapmanOrders/BMChatMessageOrder.class0000664000175000017500000000162412063430423023640 0ustar useruser2#       messageLjava/lang/String;toNamefromNameH(Lserver/Butler;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)VCodeLineNumberTableT(Lserver/Butler;Lcommunication/clientToButlerOrders/CBChatOrder;Ljava/lang/String;)V getMessage()Ljava/lang/String; getToName getFromName SourceFileBMChatMessageOrder.java ! "  .server/butlerToMapmanOrders/BMChatMessageOrder#server/butlerToMapmanOrders/BMOrder(Lserver/Butler;)V.communication/clientToButlerOrders/CBChatOrder!    >*+*,*-*"# $%& C*+*,*,*-)* +,-*0*4*8Faunis/bin/server/butlerToMapmanOrders/BMMapInfoOrder.class0000664000175000017500000000041512063430423023002 0ustar useruser2    (Lserver/Butler;)VCodeLineNumberTable SourceFileBMMapInfoOrder.java *server/butlerToMapmanOrders/BMMapInfoOrder#server/butlerToMapmanOrders/BMOrder!"*+  Faunis/bin/server/butlerToMapmanOrders/BMMoveOrder.class0000664000175000017500000000154012063430423022357 0ustar useruser2%       !"playerLserver/Player;xTargetIyTargetQ(Lserver/Player;Lserver/Butler;Lcommunication/clientToButlerOrders/CBMoveOrder;)VCodeLineNumberTable#(Lserver/Player;Lserver/Butler;II)V getXTarget()I getYTarget getPlayer()Lserver/Player; SourceFileBMMoveOrder.java # $   'server/butlerToMapmanOrders/BMMoveOrder#server/butlerToMapmanOrders/BMOrder(Lserver/Butler;)V.communication/clientToButlerOrders/CBMoveOrder!   C*,*+*-*- ! "#$>*,*+**'( )*+*.*2*6Faunis/bin/server/butlerToMapmanOrders/BMRegisterOrder.class0000664000175000017500000000106012063430423023232 0ustar useruser2   playerLserver/Player;addPlayerMapEntryZ"(Lserver/Butler;Lserver/Player;Z)VCodeLineNumberTable getPlayer()Lserver/Player;getAddPlayerMapEntry()Z SourceFileBMRegisterOrder.java    +server/butlerToMapmanOrders/BMRegisterOrder#server/butlerToMapmanOrders/BMOrder(Lserver/Butler;)V!   4*+*,*    * # * 'Faunis/bin/server/butlerToMapmanOrders/BMOrder.class0000664000175000017500000000056212063430423021533 0ustar useruser2  sourceLserver/Butler;(Lserver/Butler;)VCodeLineNumberTable getSource()Lserver/Butler; SourceFile BMOrder.java  #server/butlerToMapmanOrders/BMOrderjava/lang/Object()V! * **+    *  Faunis/bin/server/Reception.class0000664000175000017500000000261412063430423016060 0ustar useruser2` 7 8 9 :; < => ? @AB CDE F GH I J K LM ?NO PQR RecRunnable InnerClasses stopRunningZparentLserver/MainServer;portI recThreadLjava/lang/Thread; recRunnableLjava/lang/Runnable; recSocketLjava/net/ServerSocket;(Lserver/MainServer;I)VCodeLineNumberTable StackMapTableQS>shutdown()VM SourceFileReception.java *3  ! "#java/net/ServerSocket *T ()java/lang/Exception U3V WX!Couldn't create reception socket!Y Z[server/Reception$RecRunnable *\ &'java/lang/Thread *] $% ^3 _3java/io/IOExceptionjava/lang/RuntimeException Couldn't choke reception thread! *[server/Receptionjava/lang/Objectserver/MainServer(I)VprintStackTracejava/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintln(Ljava/lang/String;)V(Lserver/Reception;)V(Ljava/lang/Runnable;)Vstartclose! !"#$%&'()*+,U***+**Y*N-  * Y**Y**"%-6 &' (),"0%-&.*/21>2M3T4.%/01 23,d**L+Y -PR VSTUW.O456  Faunis/bin/server/ServerSettings.class0000664000175000017500000000470112063430423017116 0ustar useruser2 ,FG +HI +J +K +LM +N ,O PQ RS TU VW XY +Z[ \] ^_ F ` ab cd +ef +gh +ij +k l m nopq rstuvw classPathLjava/lang/String;serverDataPathclientDataPath accountPathplayerGraphicsPathimageFileEnding starterRegionmaxPlayersPerAccountI receptionPortserverSourceAt()VCodeLineNumberTable StackMapTablev[()Ljava/lang/String;()I checkPaths] SourceFileServerSettings.java 9:.png 3. greenFields 4. 56 76http://savannah.nongnu.org 8. xyz {|} ~   @ -.java/lang/Exception : java/io/File 9java/lang/StringBuilder @ / @ serverData/ /. clientData/ 0. accounts/ 1.playerGraphics/ 2.  WARNING: Account directory doesn't exist! #WARNING: Player graphics directory  doesn't exist!server/ServerSettingsjava/lang/ObjectgetClass()Ljava/lang/Class;java/lang/ClassgetProtectionDomain"()Ljava/security/ProtectionDomain;java/security/ProtectionDomain getCodeSource()Ljava/security/CodeSource;java/security/CodeSource getLocation()Ljava/net/URL; java/net/URLtoURI()Ljava/net/URI; java/net/URIgetPathprintStackTrace(Ljava/lang/String;)V getParentappend-(Ljava/lang/String;)Ljava/lang/StringBuilder;toStringexists()Z isDirectoryjava/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintln!+, -./.0.1.2.3.4.56768. 9:;B****** **  L+Y*LY+M*Y,*Y,*Y* *Y*!""9<<J#  !"%9*<'=(A)B,N-e.|/012=<>?1@;* <54@;*<93@;*<=2@;*"<A5A;*<E8@;* <I7A;*<MB:;wY* L+# +$$%Y&* '(Y* M,# ,$$%Y)*"*(<Q RS;UGVUWvY=C C DEFaunis/bin/server/Reception$RecRunnable.class0000664000175000017500000000223512063430423020244 0ustar useruser2L   !"# $% &' &( )*+ ,-. &/ 01256this$0Lserver/Reception;(Lserver/Reception;)VCodeLineNumberTablerun()V StackMapTable+7 SourceFileReception.java  8 9:Reception runnable runs; <=> ?@ ABC DEjava/io/IOException F.Error while listening to the reception socket!Client heard, create butler ... GHI JKserver/Reception$RecRunnable RecRunnable InnerClassesjava/lang/Objectjava/lang/Runnablejava/net/Socketjava/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintln(Ljava/lang/String;)Vserver/Reception stopRunningZ recSocketLjava/net/ServerSocket;java/net/ServerSocketaccept()Ljava/net/Socket;printStackTraceparentLserver/MainServer;server/MainServer createButler"(Ljava/net/Socket;)Lserver/Butler; " *+*7F*6*LM,   * +WƱ 2 9:BG C!D%E-F.H6IBJEKW 4 &3Faunis/AUTHORS.txt0000644000175000017500000000003212061463622012704 0ustar useruserSimon Ley: Everything :o] Faunis/windows.txt0000644000175000017500000000250212062725726013264 0ustar useruserCopyright 2012 Simon Ley alias "skarute" This documentation is published under the GNU Free Documentation License v1.3 or later. You can find a copy of this license in "fdl-1.3.txt" or at . ######################################## Notes for Windows users ######################################## Line Feed Problem: If you can't read the various text files of Faunis because of line feeds shown incorrectly, try opening them with WordPad instead of Notepad. Windows users without "eclipse" and "make" may execute these commands from the Makefile in the command prompt: To compile: javac -sourcepath ./src/ -cp ./bin/ -d ./bin/ ./src/client/Client.java javac -sourcepath ./src/ -cp ./bin/ -d ./bin/ ./src/server/MainServer.java To run: java -ea -cp ./bin/ client/Client java -ea -cp ./bin/ server/Server Remember to put the path of javac.exe and java.exe in your PATH environment variable, otherwise the "javac" and "java" commands may not be recognised. For javac.exe, this might look like "C:\Program Files\Java\JDK 6\bin", though the exact path depends on where you installed the JDK. --------------------------------------- The creator of Faunis recommends you to use free software and a free operating system. :o] Read more about it here: http://www.fsf.org/about/what-is-free-software Faunis/LICENSE.txt0000644000175000017500000010333012057577750012663 0ustar useruser GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software. A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public. The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version. An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU Affero General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Remote Network Interaction; Use with the GNU General Public License. Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see .