--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ 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
+this service 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.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+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
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE 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.
+
+ 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
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
--- /dev/null
+
+README
+------
+This is a library containing some common utilities and classes betwen
+server and client.
+
+This is primarily classes and utilities for handling the client<>server
+protocol.
+
+LICENSE
+-------
+ DuskZ is free software, see COPYING for your rights.
+
+ Some files are under other compatible licenses.
+
+ Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+
+ DuskZ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ DuskZ 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DuskZ; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See commented blocks below for -->
+<!-- some examples of how to customize the build. -->
+<!-- (If you delete it and reopen the project it will be recreated.) -->
+<!-- By default, only the Clean and Build commands use this build script. -->
+<!-- Commands such as Run, Debug, and Test only use this build script if -->
+<!-- the Compile on Save feature is turned off for the project. -->
+<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
+<!-- in the project's Project Properties dialog box.-->
+<project name="DuskCommon" default="default" basedir=".">
+ <description>Builds, tests, and runs the project DuskCommon.</description>
+ <import file="nbproject/build-impl.xml"/>
+ <!--
+
+ There exist several targets which are by default empty and which can be
+ used for execution of your tasks. These targets are usually executed
+ before and after some main targets. They are:
+
+ -pre-init: called before initialization of project properties
+ -post-init: called after initialization of project properties
+ -pre-compile: called before javac compilation
+ -post-compile: called after javac compilation
+ -pre-compile-single: called before javac compilation of single file
+ -post-compile-single: called after javac compilation of single file
+ -pre-compile-test: called before javac compilation of JUnit tests
+ -post-compile-test: called after javac compilation of JUnit tests
+ -pre-compile-test-single: called before javac compilation of single JUnit test
+ -post-compile-test-single: called after javac compilation of single JUunit test
+ -pre-jar: called before JAR building
+ -post-jar: called after JAR building
+ -post-clean: called after cleaning build products
+
+ (Targets beginning with '-' are not intended to be called on their own.)
+
+ Example of inserting an obfuscator after compilation could look like this:
+
+ <target name="-post-compile">
+ <obfuscate>
+ <fileset dir="${build.classes.dir}"/>
+ </obfuscate>
+ </target>
+
+ For list of available properties check the imported
+ nbproject/build-impl.xml file.
+
+
+ Another way to customize the build is by overriding existing main targets.
+ The targets of interest are:
+
+ -init-macrodef-javac: defines macro for javac compilation
+ -init-macrodef-junit: defines macro for junit execution
+ -init-macrodef-debug: defines macro for class debugging
+ -init-macrodef-java: defines macro for class execution
+ -do-jar-with-manifest: JAR building (if you are using a manifest)
+ -do-jar-without-manifest: JAR building (if you are not using a manifest)
+ run: execution of project
+ -javadoc-build: Javadoc generation
+ test-report: JUnit report generation
+
+ An example of overriding the target for project execution could look like this:
+
+ <target name="run" depends="DuskCommon-impl.jar">
+ <exec dir="bin" executable="launcher.exe">
+ <arg file="${dist.jar}"/>
+ </exec>
+ </target>
+
+ Notice that the overridden target depends on the jar target and not only on
+ the compile target as the regular run target does. Again, for a list of available
+ properties which you can use, check the target you are overriding in the
+ nbproject/build-impl.xml file.
+
+ -->
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT ***
+*** EDIT ../build.xml INSTEAD ***
+
+For the purpose of easier reading the script
+is divided into following sections:
+
+ - initialization
+ - compilation
+ - jar
+ - execution
+ - debugging
+ - javadoc
+ - test compilation
+ - test execution
+ - test debugging
+ - applet
+ - cleanup
+
+ -->
+<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="DuskCommon-impl">
+ <fail message="Please build using Ant 1.8.0 or higher.">
+ <condition>
+ <not>
+ <antversion atleast="1.8.0"/>
+ </not>
+ </condition>
+ </fail>
+ <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
+ <!--
+ ======================
+ INITIALIZATION SECTION
+ ======================
+ -->
+ <target name="-pre-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="-pre-init" name="-init-private">
+ <property file="nbproject/private/config.properties"/>
+ <property file="nbproject/private/configs/${config}.properties"/>
+ <property file="nbproject/private/private.properties"/>
+ </target>
+ <target depends="-pre-init,-init-private" name="-init-user">
+ <property file="${user.properties.file}"/>
+ <!-- The two properties below are usually overridden -->
+ <!-- by the active platform. Just a fallback. -->
+ <property name="default.javac.source" value="1.4"/>
+ <property name="default.javac.target" value="1.4"/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user" name="-init-project">
+ <property file="nbproject/configs/${config}.properties"/>
+ <property file="nbproject/project.properties"/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
+ <available file="${manifest.file}" property="manifest.available"/>
+ <condition property="splashscreen.available">
+ <and>
+ <not>
+ <equals arg1="${application.splash}" arg2="" trim="true"/>
+ </not>
+ <available file="${application.splash}"/>
+ </and>
+ </condition>
+ <condition property="main.class.available">
+ <and>
+ <isset property="main.class"/>
+ <not>
+ <equals arg1="${main.class}" arg2="" trim="true"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="manifest.available+main.class">
+ <and>
+ <isset property="manifest.available"/>
+ <isset property="main.class.available"/>
+ </and>
+ </condition>
+ <condition property="do.archive">
+ <not>
+ <istrue value="${jar.archive.disabled}"/>
+ </not>
+ </condition>
+ <condition property="do.mkdist">
+ <and>
+ <isset property="do.archive"/>
+ <isset property="libs.CopyLibs.classpath"/>
+ <not>
+ <istrue value="${mkdist.disabled}"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="manifest.available+main.class+mkdist.available">
+ <and>
+ <istrue value="${manifest.available+main.class}"/>
+ <isset property="do.mkdist"/>
+ </and>
+ </condition>
+ <condition property="do.archive+manifest.available">
+ <and>
+ <isset property="manifest.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="do.archive+main.class.available">
+ <and>
+ <isset property="main.class.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="do.archive+splashscreen.available">
+ <and>
+ <isset property="splashscreen.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="do.archive+manifest.available+main.class">
+ <and>
+ <istrue value="${manifest.available+main.class}"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="manifest.available-mkdist.available">
+ <or>
+ <istrue value="${manifest.available}"/>
+ <isset property="do.mkdist"/>
+ </or>
+ </condition>
+ <condition property="manifest.available+main.class-mkdist.available">
+ <or>
+ <istrue value="${manifest.available+main.class}"/>
+ <isset property="do.mkdist"/>
+ </or>
+ </condition>
+ <condition property="have.tests">
+ <or>
+ <available file="${test.src.dir}"/>
+ </or>
+ </condition>
+ <condition property="have.sources">
+ <or>
+ <available file="${src.dir}"/>
+ </or>
+ </condition>
+ <condition property="netbeans.home+have.tests">
+ <and>
+ <isset property="netbeans.home"/>
+ <isset property="have.tests"/>
+ </and>
+ </condition>
+ <condition property="no.javadoc.preview">
+ <and>
+ <isset property="javadoc.preview"/>
+ <isfalse value="${javadoc.preview}"/>
+ </and>
+ </condition>
+ <property name="run.jvmargs" value=""/>
+ <property name="run.jvmargs.ide" value=""/>
+ <property name="javac.compilerargs" value=""/>
+ <property name="work.dir" value="${basedir}"/>
+ <condition property="no.deps">
+ <and>
+ <istrue value="${no.dependencies}"/>
+ </and>
+ </condition>
+ <property name="javac.debug" value="true"/>
+ <property name="javadoc.preview" value="true"/>
+ <property name="application.args" value=""/>
+ <property name="source.encoding" value="${file.encoding}"/>
+ <property name="runtime.encoding" value="${source.encoding}"/>
+ <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
+ <and>
+ <isset property="javadoc.encoding"/>
+ <not>
+ <equals arg1="${javadoc.encoding}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <property name="javadoc.encoding.used" value="${source.encoding}"/>
+ <property name="includes" value="**"/>
+ <property name="excludes" value=""/>
+ <property name="do.depend" value="false"/>
+ <condition property="do.depend.true">
+ <istrue value="${do.depend}"/>
+ </condition>
+ <path id="endorsed.classpath.path" path="${endorsed.classpath}"/>
+ <condition else="" property="endorsed.classpath.cmd.line.arg" value="-Xbootclasspath/p:'${toString:endorsed.classpath.path}'">
+ <length length="0" string="${endorsed.classpath}" when="greater"/>
+ </condition>
+ <condition else="false" property="jdkBug6558476">
+ <and>
+ <matches pattern="1\.[56]" string="${java.specification.version}"/>
+ <not>
+ <os family="unix"/>
+ </not>
+ </and>
+ </condition>
+ <property name="javac.fork" value="${jdkBug6558476}"/>
+ <property name="jar.index" value="false"/>
+ <property name="jar.index.metainf" value="${jar.index}"/>
+ <property name="copylibs.rebase" value="true"/>
+ <available file="${meta.inf.dir}/persistence.xml" property="has.persistence.xml"/>
+ <condition property="junit.available">
+ <or>
+ <available classname="org.junit.Test" classpath="${run.test.classpath}"/>
+ <available classname="junit.framework.Test" classpath="${run.test.classpath}"/>
+ </or>
+ </condition>
+ <condition property="testng.available">
+ <available classname="org.testng.annotations.Test" classpath="${run.test.classpath}"/>
+ </condition>
+ <condition property="junit+testng.available">
+ <and>
+ <istrue value="${junit.available}"/>
+ <istrue value="${testng.available}"/>
+ </and>
+ </condition>
+ <condition else="testng" property="testng.mode" value="mixed">
+ <istrue value="${junit+testng.available}"/>
+ </condition>
+ <condition else="" property="testng.debug.mode" value="-mixed">
+ <istrue value="${junit+testng.available}"/>
+ </condition>
+ </target>
+ <target name="-post-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
+ <fail unless="src.dir">Must set src.dir</fail>
+ <fail unless="test.src.dir">Must set test.src.dir</fail>
+ <fail unless="build.dir">Must set build.dir</fail>
+ <fail unless="dist.dir">Must set dist.dir</fail>
+ <fail unless="build.classes.dir">Must set build.classes.dir</fail>
+ <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
+ <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
+ <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
+ <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
+ <fail unless="dist.jar">Must set dist.jar</fail>
+ </target>
+ <target name="-init-macrodef-property">
+ <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute name="name"/>
+ <attribute name="value"/>
+ <sequential>
+ <property name="@{name}" value="${@{value}}"/>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors">
+ <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <attribute default="${javac.processorpath}" name="processorpath"/>
+ <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="${javac.debug}" name="debug"/>
+ <attribute default="${empty.dir}" name="sourcepath"/>
+ <attribute default="${empty.dir}" name="gensrcdir"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.dir}/empty" name="empty.dir"/>
+ <mkdir dir="${empty.dir}"/>
+ <mkdir dir="@{apgeneratedsrcdir}"/>
+ <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+ <src>
+ <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </src>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <compilerarg line="${javac.compilerargs}"/>
+ <compilerarg value="-processorpath"/>
+ <compilerarg path="@{processorpath}:${empty.dir}"/>
+ <compilerarg line="${ap.processors.internal}"/>
+ <compilerarg line="${annotation.processing.processor.options}"/>
+ <compilerarg value="-s"/>
+ <compilerarg path="@{apgeneratedsrcdir}"/>
+ <compilerarg line="${ap.proc.none.internal}"/>
+ <customize/>
+ </javac>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-ap-cmdline-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal">
+ <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <attribute default="${javac.processorpath}" name="processorpath"/>
+ <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="${javac.debug}" name="debug"/>
+ <attribute default="${empty.dir}" name="sourcepath"/>
+ <attribute default="${empty.dir}" name="gensrcdir"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.dir}/empty" name="empty.dir"/>
+ <mkdir dir="${empty.dir}"/>
+ <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+ <src>
+ <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </src>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <compilerarg line="${javac.compilerargs}"/>
+ <customize/>
+ </javac>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac">
+ <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <sequential>
+ <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ </depend>
+ </sequential>
+ </macrodef>
+ <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <sequential>
+ <fail unless="javac.includes">Must set javac.includes</fail>
+ <pathconvert pathsep="${line.separator}" property="javac.includes.binary">
+ <path>
+ <filelist dir="@{destdir}" files="${javac.includes}"/>
+ </path>
+ <globmapper from="*.java" to="*.class"/>
+ </pathconvert>
+ <tempfile deleteonexit="true" property="javac.includesfile.binary"/>
+ <echo file="${javac.includesfile.binary}" message="${javac.includes.binary}"/>
+ <delete>
+ <files includesfile="${javac.includesfile.binary}"/>
+ </delete>
+ <delete>
+ <fileset file="${javac.includesfile.binary}"/>
+ </delete>
+ </sequential>
+ </macrodef>
+ </target>
+ <target if="${junit.available}" name="-init-macrodef-junit-init">
+ <condition else="false" property="nb.junit.batch" value="true">
+ <and>
+ <istrue value="${junit.available}"/>
+ <not>
+ <isset property="test.method"/>
+ </not>
+ </and>
+ </condition>
+ <condition else="false" property="nb.junit.single" value="true">
+ <and>
+ <istrue value="${junit.available}"/>
+ <isset property="test.method"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-init-test-properties">
+ <property name="test.binaryincludes" value="<nothing>"/>
+ <property name="test.binarytestincludes" value=""/>
+ <property name="test.binaryexcludes" value=""/>
+ </target>
+ <target if="${nb.junit.single}" name="-init-macrodef-junit-single" unless="${nb.junit.batch}">
+ <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+ <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-test-properties" if="${nb.junit.batch}" name="-init-macrodef-junit-batch" unless="${nb.junit.single}">
+ <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+ <batchtest todir="${build.test.results.dir}">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
+ <filename name="${test.binarytestincludes}"/>
+ </fileset>
+ </batchtest>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit-init,-init-macrodef-junit-single, -init-macrodef-junit-batch" if="${junit.available}" name="-init-macrodef-junit"/>
+ <target if="${testng.available}" name="-init-macrodef-testng">
+ <macrodef name="testng" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <condition else="" property="testng.methods.arg" value="@{testincludes}.@{testmethods}">
+ <isset property="test.method"/>
+ </condition>
+ <union id="test.set">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ </union>
+ <taskdef classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}" name="testng"/>
+ <testng classfilesetref="test.set" failureProperty="tests.failed" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="DuskCommon" testname="TestNG tests" workingDir="${work.dir}">
+ <xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/>
+ <propertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </propertyset>
+ <customize/>
+ </testng>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-test-impl">
+ <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <echo>No tests executed.</echo>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit" if="${junit.available}" name="-init-macrodef-junit-impl">
+ <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <j2seproject3:junit excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize/>
+ </j2seproject3:junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-testng" if="${testng.available}" name="-init-macrodef-testng-impl">
+ <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <j2seproject3:testng excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize/>
+ </j2seproject3:testng>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-test-impl,-init-macrodef-junit-impl,-init-macrodef-testng-impl" name="-init-macrodef-test">
+ <macrodef name="test" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <sequential>
+ <j2seproject3:test-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ </customize>
+ </j2seproject3:test-impl>
+ </sequential>
+ </macrodef>
+ </target>
+ <target if="${junit.available}" name="-init-macrodef-junit-debug" unless="${nb.junit.batch}">
+ <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+ <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-test-properties" if="${nb.junit.batch}" name="-init-macrodef-junit-debug-batch">
+ <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+ <batchtest todir="${build.test.results.dir}">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
+ <filename name="${test.binarytestincludes}"/>
+ </fileset>
+ </batchtest>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit-debug,-init-macrodef-junit-debug-batch" if="${junit.available}" name="-init-macrodef-junit-debug-impl">
+ <macrodef name="test-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <j2seproject3:junit-debug excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize/>
+ </j2seproject3:junit-debug>
+ </sequential>
+ </macrodef>
+ </target>
+ <target if="${testng.available}" name="-init-macrodef-testng-debug">
+ <macrodef name="testng-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <element name="customize2" optional="true"/>
+ <sequential>
+ <condition else="-testclass @{testClass}" property="test.class.or.method" value="-methods @{testClass}.@{testMethod}">
+ <isset property="test.method"/>
+ </condition>
+ <condition else="-suitename DuskCommon -testname @{testClass} ${test.class.or.method}" property="testng.cmd.args" value="@{testClass}">
+ <matches pattern=".*\.xml" string="@{testClass}"/>
+ </condition>
+ <delete dir="${build.test.results.dir}" quiet="true"/>
+ <mkdir dir="${build.test.results.dir}"/>
+ <j2seproject3:debug classname="org.testng.TestNG" classpath="${debug.test.classpath}">
+ <customize>
+ <customize2/>
+ <jvmarg value="-ea"/>
+ <arg line="${testng.debug.mode}"/>
+ <arg line="-d ${build.test.results.dir}"/>
+ <arg line="-listener org.testng.reporters.VerboseReporter"/>
+ <arg line="${testng.cmd.args}"/>
+ </customize>
+ </j2seproject3:debug>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-testng-debug" if="${testng.available}" name="-init-macrodef-testng-debug-impl">
+ <macrodef name="testng-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <element implicit="true" name="customize2" optional="true"/>
+ <sequential>
+ <j2seproject3:testng-debug testClass="@{testClass}" testMethod="@{testMethod}">
+ <customize2/>
+ </j2seproject3:testng-debug>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit-debug-impl" if="${junit.available}" name="-init-macrodef-test-debug-junit">
+ <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <sequential>
+ <j2seproject3:test-debug-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ </customize>
+ </j2seproject3:test-debug-impl>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-testng-debug-impl" if="${testng.available}" name="-init-macrodef-test-debug-testng">
+ <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <sequential>
+ <j2seproject3:testng-debug-impl testClass="@{testClass}" testMethod="@{testMethod}">
+ <customize2>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ </customize2>
+ </j2seproject3:testng-debug-impl>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-test-debug-junit,-init-macrodef-test-debug-testng" name="-init-macrodef-test-debug"/>
+ <!--
+ pre NB7.2 profiling section; consider it deprecated
+ -->
+ <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile, -profile-init-check" if="profiler.info.jvmargs.agent" name="profile-init"/>
+ <target if="profiler.info.jvmargs.agent" name="-profile-pre-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="profiler.info.jvmargs.agent" name="-profile-post-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="profiler.info.jvmargs.agent" name="-profile-init-macrodef-profile">
+ <macrodef name="resolve">
+ <attribute name="name"/>
+ <attribute name="value"/>
+ <sequential>
+ <property name="@{name}" value="${env.@{value}}"/>
+ </sequential>
+ </macrodef>
+ <macrodef name="profile">
+ <attribute default="${main.class}" name="classname"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property environment="env"/>
+ <resolve name="profiler.current.path" value="${profiler.info.pathvar}"/>
+ <java classname="@{classname}" dir="${profiler.info.dir}" fork="true" jvm="${profiler.info.jvm}">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg value="${profiler.info.jvmargs.agent}"/>
+ <jvmarg line="${profiler.info.jvmargs}"/>
+ <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
+ <arg line="${application.args}"/>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile" if="profiler.info.jvmargs.agent" name="-profile-init-check">
+ <fail unless="profiler.info.jvm">Must set JVM to use for profiling in profiler.info.jvm</fail>
+ <fail unless="profiler.info.jvmargs.agent">Must set profiler agent JVM arguments in profiler.info.jvmargs.agent</fail>
+ </target>
+ <!--
+ end of pre NB7.2 profiling section
+ -->
+ <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
+ <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${main.class}" name="name"/>
+ <attribute default="${debug.classpath}" name="classpath"/>
+ <attribute default="" name="stopclassname"/>
+ <sequential>
+ <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ </nbjpdastart>
+ </sequential>
+ </macrodef>
+ <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${build.classes.dir}" name="dir"/>
+ <sequential>
+ <nbjpdareload>
+ <fileset dir="@{dir}" includes="${fix.classes}">
+ <include name="${fix.includes}*.class"/>
+ </fileset>
+ </nbjpdareload>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-debug-args">
+ <property name="version-output" value="java version "${ant.java.version}"/>
+ <condition property="have-jdk-older-than-1.4">
+ <or>
+ <contains string="${version-output}" substring="java version "1.0"/>
+ <contains string="${version-output}" substring="java version "1.1"/>
+ <contains string="${version-output}" substring="java version "1.2"/>
+ <contains string="${version-output}" substring="java version "1.3"/>
+ </or>
+ </condition>
+ <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
+ <istrue value="${have-jdk-older-than-1.4}"/>
+ </condition>
+ <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
+ <os family="windows"/>
+ </condition>
+ <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
+ <isset property="debug.transport"/>
+ </condition>
+ </target>
+ <target depends="-init-debug-args" name="-init-macrodef-debug">
+ <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="classname"/>
+ <attribute default="${debug.classpath}" name="classpath"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <java classname="@{classname}" dir="${work.dir}" fork="true">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+ <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-java">
+ <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${main.class}" name="classname"/>
+ <attribute default="${run.classpath}" name="classpath"/>
+ <attribute default="jvm" name="jvm"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <java classname="@{classname}" dir="${work.dir}" fork="true">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+ <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-copylibs">
+ <macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${manifest.file}" name="manifest"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <pathconvert property="run.classpath.without.build.classes.dir">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to=""/>
+ </pathconvert>
+ <pathconvert pathsep=" " property="jar.classpath">
+ <path path="${run.classpath.without.build.classes.dir}"/>
+ <chainedmapper>
+ <flattenmapper/>
+ <filtermapper>
+ <replacestring from=" " to="%20"/>
+ </filtermapper>
+ <globmapper from="*" to="lib/*"/>
+ </chainedmapper>
+ </pathconvert>
+ <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
+ <copylibs compress="${jar.compress}" index="${jar.index}" indexMetaInf="${jar.index.metainf}" jarfile="${dist.jar}" manifest="@{manifest}" rebase="${copylibs.rebase}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
+ <fileset dir="${build.classes.dir}"/>
+ <manifest>
+ <attribute name="Class-Path" value="${jar.classpath}"/>
+ <customize/>
+ </manifest>
+ </copylibs>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-presetdef-jar">
+ <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}">
+ <j2seproject1:fileset dir="${build.classes.dir}"/>
+ </jar>
+ </presetdef>
+ </target>
+ <target name="-init-ap-cmdline-properties">
+ <property name="annotation.processing.enabled" value="true"/>
+ <property name="annotation.processing.processors.list" value=""/>
+ <property name="annotation.processing.processor.options" value=""/>
+ <property name="annotation.processing.run.all.processors" value="true"/>
+ <property name="javac.processorpath" value="${javac.classpath}"/>
+ <property name="javac.test.processorpath" value="${javac.test.classpath}"/>
+ <condition property="ap.supported.internal" value="true">
+ <not>
+ <matches pattern="1\.[0-5](\..*)?" string="${javac.source}"/>
+ </not>
+ </condition>
+ </target>
+ <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-ap-cmdline-supported">
+ <condition else="" property="ap.processors.internal" value="-processor ${annotation.processing.processors.list}">
+ <isfalse value="${annotation.processing.run.all.processors}"/>
+ </condition>
+ <condition else="" property="ap.proc.none.internal" value="-proc:none">
+ <isfalse value="${annotation.processing.enabled}"/>
+ </condition>
+ </target>
+ <target depends="-init-ap-cmdline-properties,-init-ap-cmdline-supported" name="-init-ap-cmdline">
+ <property name="ap.cmd.line.internal" value=""/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-test,-init-macrodef-test-debug,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar,-init-ap-cmdline" name="init"/>
+ <!--
+ ===================
+ COMPILATION SECTION
+ ===================
+ -->
+ <target name="-deps-jar-init" unless="built-jar.properties">
+ <property location="${build.dir}/built-jar.properties" name="built-jar.properties"/>
+ <delete file="${built-jar.properties}" quiet="true"/>
+ </target>
+ <target if="already.built.jar.${basedir}" name="-warn-already-built-jar">
+ <echo level="warn" message="Cycle detected: DuskCommon was already built"/>
+ </target>
+ <target depends="init,-deps-jar-init" name="deps-jar" unless="no.deps">
+ <mkdir dir="${build.dir}"/>
+ <touch file="${built-jar.properties}" verbose="false"/>
+ <property file="${built-jar.properties}" prefix="already.built.jar."/>
+ <antcall target="-warn-already-built-jar"/>
+ <propertyfile file="${built-jar.properties}">
+ <entry key="${basedir}" value=""/>
+ </propertyfile>
+ </target>
+ <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
+ <target depends="init" name="-check-automatic-build">
+ <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
+ </target>
+ <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
+ <antcall target="clean"/>
+ </target>
+ <target depends="init,deps-jar" name="-pre-pre-compile">
+ <mkdir dir="${build.classes.dir}"/>
+ </target>
+ <target name="-pre-compile">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="do.depend.true" name="-compile-depend">
+ <pathconvert property="build.generated.subdirs">
+ <dirset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </pathconvert>
+ <j2seproject3:depend srcdir="${src.dir}:${build.generated.subdirs}"/>
+ </target>
+ <target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,-compile-depend" if="have.sources" name="-do-compile">
+ <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/>
+ <copy todir="${build.classes.dir}">
+ <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target if="has.persistence.xml" name="-copy-persistence-xml">
+ <mkdir dir="${build.classes.dir}/META-INF"/>
+ <copy todir="${build.classes.dir}/META-INF">
+ <fileset dir="${meta.inf.dir}" includes="persistence.xml orm.xml"/>
+ </copy>
+ </target>
+ <target name="-post-compile">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
+ <target name="-pre-compile-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
+ <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+ <j2seproject3:force-recompile/>
+ <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.dir}"/>
+ </target>
+ <target name="-post-compile-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
+ <!--
+ ====================
+ JAR BUILDING SECTION
+ ====================
+ -->
+ <target depends="init" name="-pre-pre-jar">
+ <dirname file="${dist.jar}" property="dist.jar.dir"/>
+ <mkdir dir="${dist.jar.dir}"/>
+ </target>
+ <target name="-pre-jar">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive" name="-do-jar-without-manifest" unless="manifest.available-mkdist.available">
+ <j2seproject1:jar/>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class-mkdist.available">
+ <j2seproject1:jar manifest="${manifest.file}"/>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
+ <j2seproject1:jar manifest="${manifest.file}">
+ <j2seproject1:manifest>
+ <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
+ </j2seproject1:manifest>
+ </j2seproject1:jar>
+ <echo level="info">To run this application from the command line without Ant, try:</echo>
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <property location="${dist.jar}" name="dist.jar.resolved"/>
+ <pathconvert property="run.classpath.with.dist.jar">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
+ </pathconvert>
+ <echo level="info">java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
+ </target>
+ <target depends="init" if="do.archive" name="-do-jar-with-libraries-create-manifest" unless="manifest.available">
+ <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
+ <touch file="${tmp.manifest.file}" verbose="false"/>
+ </target>
+ <target depends="init" if="do.archive+manifest.available" name="-do-jar-with-libraries-copy-manifest">
+ <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
+ <copy file="${manifest.file}" tofile="${tmp.manifest.file}"/>
+ </target>
+ <target depends="init,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest" if="do.archive+main.class.available" name="-do-jar-with-libraries-set-main">
+ <manifest file="${tmp.manifest.file}" mode="update">
+ <attribute name="Main-Class" value="${main.class}"/>
+ </manifest>
+ </target>
+ <target depends="init,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest" if="do.archive+splashscreen.available" name="-do-jar-with-libraries-set-splashscreen">
+ <basename file="${application.splash}" property="splashscreen.basename"/>
+ <mkdir dir="${build.classes.dir}/META-INF"/>
+ <copy failonerror="false" file="${application.splash}" todir="${build.classes.dir}/META-INF"/>
+ <manifest file="${tmp.manifest.file}" mode="update">
+ <attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/>
+ </manifest>
+ </target>
+ <target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest,-do-jar-with-libraries-set-main,-do-jar-with-libraries-set-splashscreen" if="do.mkdist" name="-do-jar-with-libraries-pack">
+ <j2seproject3:copylibs manifest="${tmp.manifest.file}"/>
+ <echo level="info">To run this application from the command line without Ant, try:</echo>
+ <property location="${dist.jar}" name="dist.jar.resolved"/>
+ <echo level="info">java -jar "${dist.jar.resolved}"</echo>
+ </target>
+ <target depends="-do-jar-with-libraries-pack" if="do.archive" name="-do-jar-with-libraries-delete-manifest">
+ <delete>
+ <fileset file="${tmp.manifest.file}"/>
+ </delete>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest,-do-jar-with-libraries-set-main,-do-jar-with-libraries-set-splashscreen,-do-jar-with-libraries-pack,-do-jar-with-libraries-delete-manifest" name="-do-jar-with-libraries"/>
+ <target name="-post-jar">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
+ <!--
+ =================
+ EXECUTION SECTION
+ =================
+ -->
+ <target depends="init,compile" description="Run a main class." name="run">
+ <j2seproject1:java>
+ <customize>
+ <arg line="${application.args}"/>
+ </customize>
+ </j2seproject1:java>
+ </target>
+ <target name="-do-not-recompile">
+ <property name="javac.includes.binary" value=""/>
+ </target>
+ <target depends="init,compile-single" name="run-single">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <j2seproject1:java classname="${run.class}"/>
+ </target>
+ <target depends="init,compile-test-single" name="run-test-with-main">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/>
+ </target>
+ <!--
+ =================
+ DEBUGGING SECTION
+ =================
+ -->
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger">
+ <j2seproject1:nbjpdastart name="${debug.class}"/>
+ </target>
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger-main-test">
+ <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${debug.class}"/>
+ </target>
+ <target depends="init,compile" name="-debug-start-debuggee">
+ <j2seproject3:debug>
+ <customize>
+ <arg line="${application.args}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
+ <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
+ </target>
+ <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
+ <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
+ <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+ <j2seproject3:debug classname="${debug.class}"/>
+ </target>
+ <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
+ <target depends="init,compile-test-single" if="netbeans.home" name="-debug-start-debuggee-main-test">
+ <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+ <j2seproject3:debug classname="${debug.class}" classpath="${debug.test.classpath}"/>
+ </target>
+ <target depends="init,compile-test-single,-debug-start-debugger-main-test,-debug-start-debuggee-main-test" if="netbeans.home" name="debug-test-with-main"/>
+ <target depends="init" name="-pre-debug-fix">
+ <fail unless="fix.includes">Must set fix.includes</fail>
+ <property name="javac.includes" value="${fix.includes}.java"/>
+ </target>
+ <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
+ <j2seproject1:nbjpdareload/>
+ </target>
+ <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
+ <!--
+ =================
+ PROFILING SECTION
+ =================
+ -->
+ <!--
+ pre NB7.2 profiler integration
+ -->
+ <target depends="profile-init,compile" description="Profile a project in the IDE." if="profiler.info.jvmargs.agent" name="-profile-pre72">
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <profile/>
+ </target>
+ <target depends="profile-init,compile-single" description="Profile a selected class in the IDE." if="profiler.info.jvmargs.agent" name="-profile-single-pre72">
+ <fail unless="profile.class">Must select one file in the IDE or set profile.class</fail>
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <profile classname="${profile.class}"/>
+ </target>
+ <target depends="profile-init,compile-single" if="profiler.info.jvmargs.agent" name="-profile-applet-pre72">
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <profile classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </profile>
+ </target>
+ <target depends="profile-init,compile-test-single" if="profiler.info.jvmargs.agent" name="-profile-test-single-pre72">
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <junit dir="${profiler.info.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" jvm="${profiler.info.jvm}" showoutput="true">
+ <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
+ <jvmarg value="${profiler.info.jvmargs.agent}"/>
+ <jvmarg line="${profiler.info.jvmargs}"/>
+ <test name="${profile.class}"/>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ </junit>
+ </target>
+ <!--
+ end of pre NB72 profiling section
+ -->
+ <target if="netbeans.home" name="-profile-check">
+ <condition property="profiler.configured">
+ <or>
+ <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-agentpath:"/>
+ <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-javaagent:"/>
+ </or>
+ </condition>
+ </target>
+ <target depends="-profile-check,-profile-pre72" description="Profile a project in the IDE." if="profiler.configured" name="profile" unless="profiler.info.jvmargs.agent">
+ <startprofiler/>
+ <antcall target="run"/>
+ </target>
+ <target depends="-profile-check,-profile-single-pre72" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-single" unless="profiler.info.jvmargs.agent">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <startprofiler/>
+ <antcall target="run-single"/>
+ </target>
+ <target depends="-profile-test-single-pre72" description="Profile a selected test in the IDE." name="profile-test-single"/>
+ <target depends="-profile-check" description="Profile a selected test in the IDE." if="profiler.configured" name="profile-test" unless="profiler.info.jvmargs">
+ <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+ <startprofiler/>
+ <antcall target="test-single"/>
+ </target>
+ <target depends="-profile-check" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-test-with-main">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <startprofiler/>
+ <antcal target="run-test-with-main"/>
+ </target>
+ <target depends="-profile-check,-profile-applet-pre72" if="profiler.configured" name="profile-applet" unless="profiler.info.jvmargs.agent">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <startprofiler/>
+ <antcall target="run-applet"/>
+ </target>
+ <!--
+ ===============
+ JAVADOC SECTION
+ ===============
+ -->
+ <target depends="init" if="have.sources" name="-javadoc-build">
+ <mkdir dir="${dist.javadoc.dir}"/>
+ <condition else="" property="javadoc.endorsed.classpath.cmd.line.arg" value="-J${endorsed.classpath.cmd.line.arg}">
+ <and>
+ <isset property="endorsed.classpath.cmd.line.arg"/>
+ <not>
+ <equals arg1="${endorsed.classpath.cmd.line.arg}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
+ <classpath>
+ <path path="${javac.classpath}"/>
+ </classpath>
+ <fileset dir="${src.dir}" excludes="*.java,${excludes}" includes="${includes}">
+ <filename name="**/*.java"/>
+ </fileset>
+ <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="**/*.java"/>
+ <exclude name="*.java"/>
+ </fileset>
+ <arg line="${javadoc.endorsed.classpath.cmd.line.arg}"/>
+ </javadoc>
+ <copy todir="${dist.javadoc.dir}">
+ <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
+ <filename name="**/doc-files/**"/>
+ </fileset>
+ <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="**/doc-files/**"/>
+ </fileset>
+ </copy>
+ </target>
+ <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
+ <nbbrowse file="${dist.javadoc.dir}/index.html"/>
+ </target>
+ <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
+ <!--
+ =========================
+ TEST COMPILATION SECTION
+ =========================
+ -->
+ <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
+ <mkdir dir="${build.test.classes.dir}"/>
+ </target>
+ <target name="-pre-compile-test">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="do.depend.true" name="-compile-test-depend">
+ <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
+ </target>
+ <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
+ <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" processorpath="${javac.test.processorpath}" srcdir="${test.src.dir}"/>
+ <copy todir="${build.test.classes.dir}">
+ <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile-test">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
+ <target name="-pre-compile-test-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
+ <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+ <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
+ <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" processorpath="${javac.test.processorpath}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
+ <copy todir="${build.test.classes.dir}">
+ <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile-test-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
+ <!--
+ =======================
+ TEST EXECUTION SECTION
+ =======================
+ -->
+ <target depends="init" if="have.tests" name="-pre-test-run">
+ <mkdir dir="${build.test.results.dir}"/>
+ </target>
+ <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
+ <j2seproject3:test testincludes="**/*Test.java"/>
+ </target>
+ <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init" if="have.tests" name="test-report"/>
+ <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
+ <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
+ <target depends="init" if="have.tests" name="-pre-test-run-single">
+ <mkdir dir="${build.test.results.dir}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
+ <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+ <j2seproject3:test excludes="" includes="${test.includes}" testincludes="${test.includes}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single-method">
+ <fail unless="test.class">Must select some files in the IDE or set test.class</fail>
+ <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
+ <j2seproject3:test excludes="" includes="${javac.includes}" testincludes="${test.class}" testmethods="${test.method}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method" if="have.tests" name="-post-test-run-single-method">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method,-post-test-run-single-method" description="Run single unit test." name="test-single-method"/>
+ <!--
+ =======================
+ TEST DEBUGGING SECTION
+ =======================
+ -->
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test">
+ <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+ <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testincludes="${javac.includes}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test-method">
+ <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+ <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
+ <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testMethod="${test.method}" testincludes="${test.class}" testmethods="${test.method}"/>
+ </target>
+ <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
+ <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
+ </target>
+ <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
+ <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test-method" name="debug-test-method"/>
+ <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
+ <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
+ </target>
+ <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
+ <!--
+ =========================
+ APPLET EXECUTION SECTION
+ =========================
+ -->
+ <target depends="init,compile-single" name="run-applet">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <j2seproject1:java classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </j2seproject1:java>
+ </target>
+ <!--
+ =========================
+ APPLET DEBUGGING SECTION
+ =========================
+ -->
+ <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <j2seproject3:debug classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
+ <!--
+ ===============
+ CLEANUP SECTION
+ ===============
+ -->
+ <target name="-deps-clean-init" unless="built-clean.properties">
+ <property location="${build.dir}/built-clean.properties" name="built-clean.properties"/>
+ <delete file="${built-clean.properties}" quiet="true"/>
+ </target>
+ <target if="already.built.clean.${basedir}" name="-warn-already-built-clean">
+ <echo level="warn" message="Cycle detected: DuskCommon was already built"/>
+ </target>
+ <target depends="init,-deps-clean-init" name="deps-clean" unless="no.deps">
+ <mkdir dir="${build.dir}"/>
+ <touch file="${built-clean.properties}" verbose="false"/>
+ <property file="${built-clean.properties}" prefix="already.built.clean."/>
+ <antcall target="-warn-already-built-clean"/>
+ <propertyfile file="${built-clean.properties}">
+ <entry key="${basedir}" value=""/>
+ </propertyfile>
+ </target>
+ <target depends="init" name="-do-clean">
+ <delete dir="${build.dir}"/>
+ <delete dir="${dist.dir}" followsymlinks="false" includeemptydirs="true"/>
+ </target>
+ <target name="-post-clean">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
+ <target name="-check-call-dep">
+ <property file="${call.built.properties}" prefix="already.built."/>
+ <condition property="should.call.dep">
+ <and>
+ <not>
+ <isset property="already.built.${call.subproject}"/>
+ </not>
+ <available file="${call.script}"/>
+ </and>
+ </condition>
+ </target>
+ <target depends="-check-call-dep" if="should.call.dep" name="-maybe-call-dep">
+ <ant antfile="${call.script}" inheritall="false" target="${call.target}">
+ <propertyset>
+ <propertyref prefix="transfer."/>
+ <mapper from="transfer.*" to="*" type="glob"/>
+ </propertyset>
+ </ant>
+ </target>
+</project>
--- /dev/null
+build.xml.data.CRC32=cb9774bc
+build.xml.script.CRC32=41ed8886
+build.xml.stylesheet.CRC32=28e38971@1.56.1.46
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=cb9774bc
+nbproject/build-impl.xml.script.CRC32=4cf1c99d
+nbproject/build-impl.xml.stylesheet.CRC32=c6d2a60f@1.56.1.46
--- /dev/null
+project.license=dusk
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.processor.options=
+annotation.processing.processors.list=
+annotation.processing.run.all.processors=true
+annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/DuskCommon.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+includes=**
+jar.compress=false
+javac.classpath=
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.processorpath=\
+ ${javac.classpath}
+javac.source=1.7
+javac.target=1.7
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+javac.test.processorpath=\
+ ${javac.test.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+meta.inf.dir=${src.dir}/META-INF
+mkdist.disabled=true
+platform.active=default_platform
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project.
+# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
+# To set system properties for unit tests define test-sys-prop.name=value:
+run.jvmargs=
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.java.j2seproject</type>
+ <configuration>
+ <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
+ <name>DuskCommon</name>
+ <source-roots>
+ <root id="src.dir"/>
+ </source-roots>
+ <test-roots>
+ <root id="test.src.dir"/>
+ </test-roots>
+ </data>
+ </configuration>
+</project>
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.protocol;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * Type of message sent from server.
+ *
+ * @author notzed
+ */
+public enum MessageType {
+
+ // 0
+ Quit,
+ UpdateImages,
+ UpdateLocMap {
+
+ @Override
+ public ServerMessage decode(DataInputStream instream) throws IOException {
+ return ServerMessage.MapMessage.decode(instream);
+ }
+ },
+ Chat,
+ AddEntity,
+ // 5
+ UpdateStats,
+ UpdateItems,
+ UpdateEquipment,
+ UpdateInfo,
+ Halt,
+ // 10
+ UpdateActions,
+ LoadMusic,
+ PlayMusic,
+ Ping,
+ Proceed,
+ // 15
+ PlaySound,
+ RemoveEntity,
+ UpdateMerchant,
+ EditText,
+ ResizeMap,
+ // 20
+ ViewText,
+ ExitMerchant,
+ UpdateSell,
+ ColourChat,
+ MoveNorth,
+ // 25
+ MoveSouth,
+ MoveWest,
+ MoveEast,
+ UpdateRange,
+ SetFlag,
+ // 30
+ ClearFlags,
+ StartBattle,
+ UpdateBattle,
+ LogBattle,
+ // Above list is compatible with original dusk, new ones follow
+ // A bunch of login/setup related stuff
+ /**
+ * Choose race, response is
+ * code header
+ * race 0
+ * race 1
+ * ...
+ * .
+ */
+ ChooseRace,
+ /**
+ * Damage (or healing) to an entity.
+ * Encoded as:
+ * targetID
+ * +-damage
+ * newhp
+ * totalhp
+ * fromID
+ * how
+ * .
+ */
+ HitEntity,;
+
+ public static MessageType fromServer(int v) {
+ return values()[v];
+ }
+
+ public char code() {
+ return (char) ordinal();
+ }
+
+ /**
+ * Not implemented yet
+ * @param instream
+ * @return
+ * @throws IOException
+ * @deprecated
+ */
+ @Deprecated
+ public ServerMessage decode(DataInputStream instream) throws IOException {
+ return null;
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.protocol;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Message from server to client
+ *
+ * @author notzed
+ */
+public abstract class ServerMessage {
+
+ final MessageType type;
+
+ public ServerMessage(MessageType type) {
+ this.type = type;
+ }
+
+ public abstract void send(DataOutputStream ostream) throws IOException;
+
+ public static ServerMessage stringMessage(String s) {
+ return new StringMessage(s);
+ }
+
+ public static ServerMessage stringMessage(MessageType type, String data) {
+ return new StringMessage(type, data);
+ }
+
+ public static ServerMessage mapMessage(int locx, int locy, short[] map) {
+ return new MapMessage(locx, locy, map);
+ }
+
+ public static ServerMessage fromServer(DataInputStream instream) throws IOException {
+ int typec = instream.readByte();
+
+ MessageType type = MessageType.values()[typec];
+ // TODO: more protocol, length? how?
+
+ return type.decode(instream);
+ }
+
+ public static class StringMessage extends ServerMessage {
+
+ final String data;
+
+ public StringMessage(String data) {
+ super(null);
+ this.data = data;
+ }
+
+ private StringMessage(MessageType type, String data) {
+ super(type);
+ this.data = data;
+ }
+
+ @Override
+ public void send(DataOutputStream ostream) throws IOException {
+ if (type != null)
+ ostream.writeByte(type.code());
+ ostream.writeBytes(data);
+ }
+
+ @Override
+ public String toString() {
+ return data;
+ }
+ }
+
+ public static class MapMessage extends ServerMessage {
+
+ public int x;
+ public int y;
+ public short[] map;
+
+ public MapMessage(int locx, int locy, short[] map) {
+ super(MessageType.UpdateLocMap);
+ this.x = locx;
+ this.y = locy;
+ this.map = map;
+ }
+
+ public static MapMessage decode(DataInputStream instream) throws IOException {
+ int x = instream.readShort();
+ int y = instream.readShort();
+ int length = instream.readInt();
+ short[] map = new short[length];
+ for (int i = 0; i < length; i++) {
+ map[i] = instream.readShort();
+ }
+ return new MapMessage(x, y, map);
+ }
+
+ @Override
+ public void send(DataOutputStream ostream) throws IOException {
+ ostream.writeByte(type.code());
+ ostream.writeShort(x);
+ ostream.writeShort(y);
+ ostream.writeInt(map.length);
+ for (int i = 0; i < map.length; i++)
+ ostream.writeShort(map[i]);
+ }
+ }
+
+ public static class EntityMessage extends ServerMessage {
+
+ public long id;
+ public String name;
+ public byte entityType;
+ public short x;
+ public short y;
+ public short image;
+ public short imageStep;
+
+ public EntityMessage(MessageType type, long id, String name, byte entityType, short x, short y, short image, short imageStep) {
+ super(type);
+ this.id = id;
+ this.name = name;
+ this.entityType = entityType;
+ this.x = x;
+ this.y = y;
+ this.image = image;
+ this.imageStep = imageStep;
+
+ System.out.printf("create entity message: %d '%s' %d %dx%d image %d %d\n",
+ id, name, entityType, x, y, image, imageStep);
+ }
+
+ public static EntityMessage decode(MessageType type, DataInputStream instream) throws IOException {
+ long id = instream.readLong();
+ String name = instream.readUTF();
+ byte entityType = instream.readByte();
+ short x = instream.readShort();
+ short y = instream.readShort();
+ short image = instream.readShort();
+ short imageStep = instream.readShort();
+
+ return new EntityMessage(type, id, name, entityType, x, y, image, imageStep);
+ }
+
+ @Override
+ public void send(DataOutputStream ostream) throws IOException {
+ ostream.writeByte(type.code());
+ ostream.writeLong(id);
+ ostream.writeUTF(name);
+ ostream.writeByte(entityType);
+ ostream.writeShort(x);
+ ostream.writeShort(y);
+ ostream.writeShort(image);
+ ostream.writeShort(imageStep);
+ }
+ }
+
+ /**
+ * Main player stats
+ */
+ public static class StatsMessage extends ServerMessage {
+
+ public long cash;
+ public int exp;
+ public int stre, strebonus;
+ public int inte, intebonus;
+ public int dext, dextbonus;
+ public int cons, consbonus;
+ public int wisd, wisdbonus;
+ public int damm, dammbonus;
+ public int ac, acbonus;
+
+ public StatsMessage(MessageType type, long cash, int exp, int stre, int strebonus,
+ int inte, int intebonus, int dext, int dextbonus, int cons, int consbonus,
+ int wisd, int wisdbonus, int damm, int dammbonus, int ac, int acbonus) {
+ super(type);
+ this.cash = cash;
+ this.exp = exp;
+ this.stre = stre;
+ this.strebonus = strebonus;
+ this.inte = inte;
+ this.intebonus = intebonus;
+ this.dext = dext;
+ this.dextbonus = dextbonus;
+ this.cons = cons;
+ this.consbonus = consbonus;
+ this.wisd = wisd;
+ this.wisdbonus = wisdbonus;
+ this.damm = damm;
+ this.dammbonus = dammbonus;
+ this.ac = ac;
+ this.acbonus = acbonus;
+ }
+
+ public static StatsMessage decode(MessageType type, DataInputStream instream) throws IOException {
+ long cash = instream.readLong();
+ int exp = instream.readInt();
+ int stre = instream.readInt();
+ int strebonus = instream.readInt();
+ int inte = instream.readInt();
+ int intebonus = instream.readInt();
+ int dext = instream.readInt();
+ int dextbonus = instream.readInt();
+ int cons = instream.readInt();
+ int consbonus = instream.readInt();
+ int wisd = instream.readInt();
+ int wisdbonus = instream.readInt();
+ int damm = instream.readInt();
+ int dammbonus = instream.readInt();
+ int ac = instream.readInt();
+ int acbonus = instream.readInt();
+
+ return new StatsMessage(type, cash, exp,
+ stre, strebonus,
+ inte, intebonus,
+ dext, dextbonus,
+ cons, consbonus,
+ wisd, wisdbonus,
+ damm, dammbonus,
+ ac, acbonus);
+ }
+
+ @Override
+ public void send(DataOutputStream ostream) throws IOException {
+ ostream.writeByte(type.code());
+ ostream.writeLong(cash);
+ ostream.writeInt(exp);
+ ostream.writeInt(stre);
+ ostream.writeInt(strebonus);
+ ostream.writeInt(inte);
+ ostream.writeInt(intebonus);
+ ostream.writeInt(dext);
+ ostream.writeInt(dextbonus);
+ ostream.writeInt(cons);
+ ostream.writeInt(consbonus);
+ ostream.writeInt(wisd);
+ ostream.writeInt(wisdbonus);
+ ostream.writeInt(damm);
+ ostream.writeInt(dammbonus);
+ ostream.writeInt(ac);
+ ostream.writeInt(acbonus);
+ }
+ }
+
+ /**
+ * Other player stats?
+ * All together or separate?
+ * UpdateSkills
+ * UpdateConditions?
+ */
+ /*
+ strResult += "-Affected by-\n";
+ for (Condition cond : conditions) {
+ if (cond.display) {
+ strResult += cond.name + "\n";
+ }
+ }
+ strResult += "-Skills-\n";
+ for (Ability skill : skillMap.values()) {
+ strResult += skill.name + ": " + skill.getAbility() + "\n";
+ }
+ strResult += "-Spells-\n";
+ for (Ability spell : spellMap.values()) {
+ grpStore = game.getSpellGroup(spell.name);
+ if (grpStore != null) {
+ strResult += spell.name + ": " + spell.getAbility() + "\n";
+ strResult += grpStore.spellList(spell.getAbility());
+ }
+ }
+ if (master != null) {
+ strResult += "\nFollowing: " + master.name + "\n";
+ }*/
+ public static class ItemsMessage extends ServerMessage {
+
+ List<TransactionItem> items;
+
+ public ItemsMessage(MessageType type, List<TransactionItem> items) {
+ super(type);
+ this.items = items;
+ }
+
+ public static ItemsMessage decode(MessageType type, DataInputStream instream) throws IOException {
+ List<TransactionItem> items = new ArrayList<>();
+
+ int count = instream.readShort();
+ for (int i = 0; i < count; i++) {
+ TransactionItem item = new TransactionItem();
+
+ item.name = instream.readUTF();
+ item.count = instream.readInt();
+ item.cost = instream.readInt();
+ item.units = instream.readUTF();
+ }
+
+ return new ItemsMessage(type, items);
+ }
+
+ @Override
+ public void send(DataOutputStream ostream) throws IOException {
+ ostream.writeByte(type.code());
+ ostream.writeShort(items.size());
+ for (TransactionItem item : items) {
+ ostream.writeUTF(item.getName());
+ ostream.writeInt(item.getCount());
+ ostream.writeInt(item.getCost());
+ ostream.writeUTF(item.getUnits());
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.protocol;
+
+/**
+ * Represents a transaction item (buy/sell) for server protocol.
+ * @author notzed
+ */
+public class TransactionItem implements Comparable<TransactionItem>{
+
+ public String name;
+ public int count;
+ public int cost;
+ public String units;
+
+ public TransactionItem() {
+ }
+
+
+ public TransactionItem(String name, int count, int cost, String units) {
+ this.name = name;
+ this.count = count;
+ this.cost = cost;
+ this.units = units;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public int getCost() {
+ return cost;
+ }
+
+ public String getUnits() {
+ return units;
+ }
+
+ @Override
+ public String toString() {
+ return cost + ") " + name + "[" + count + "]";
+ }
+
+ @Override
+ public int compareTo(TransactionItem t) {
+ return name.compareTo(t.name);
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.protocol;
+
+/**
+ * Constants for wearing locations.
+ * @author notzed
+ */
+public interface Wearing {
+
+ public static final int WIELD = 0;
+ public static final int ARMS = 1;
+ public static final int LEGS = 2;
+ public static final int TORSO = 3;
+ public static final int WAIST = 4;
+ public static final int NECK = 5;
+ public static final int SKULL = 6;
+ public static final int EYES = 7;
+ public static final int HANDS = 8;
+ public static final int WEARING_COUNT = 9;
+ public static final String[] titles = {
+ "Wielded", "Arms", "Legs", "Torso", "Waist", "Neck", "Skull", "Eyes", "Hands"
+ };
+ /**
+ * Field names as on the server
+ */
+ public static final String[] names = {
+ "wielded", "arms", "legs", "torso", "waist", "neck", "skull", "eyes", "hands"
+ };
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.util;
+
+/**
+ * Debugging utilities.
+ * @author notzed
+ */
+public class Debug {
+
+ /**
+ * Print a stack trace of the current position to stderr.
+ */
+ public static void stackTrace() {
+ try {
+ throw new Exception();
+ } catch (Exception e) {
+ System.out.println("The following stacktrace is only for debugging and is not an error");
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.util;
+
+/**
+ * Some maths utilities.
+ *
+ * @author notzed
+ */
+public class Maths {
+
+ /**
+ * Clamp an integer to (l,u) inclusive.
+ *
+ * @param v
+ * @param l
+ * @param u
+ * @return
+ */
+ public static int clamp(int v, int l, int u) {
+ v = Math.max(v, l);
+ return Math.min(v, u);
+ }
+}
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ 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
+this service 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.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+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
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE 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.
+
+ 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
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
--- /dev/null
+
+README
+------
+This is the server implementation of DuskZ. A client is required
+to access the game.
+
+It is a fork and major overhaul of the Dusk 2.7.3 source code, released
+circa 2000.
+
+This is currently in an alpha state and in very active development.
+
+ ... to be completed ...
+
+INSTALLATION
+------------
+ ... to be completed ...
+
+RUNNING
+-------
+ ... to be completed ...
+
+LICENSE
+-------
+ DuskZ is free software, see COPYING for your rights.
+
+ Some files are under other compatible licenses.
+
+ Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+
+ DuskZ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ DuskZ 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DuskZ; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See commented blocks below for -->
+<!-- some examples of how to customize the build. -->
+<!-- (If you delete it and reopen the project it will be recreated.) -->
+<!-- By default, only the Clean and Build commands use this build script. -->
+<!-- Commands such as Run, Debug, and Test only use this build script if -->
+<!-- the Compile on Save feature is turned off for the project. -->
+<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
+<!-- in the project's Project Properties dialog box.-->
+<project name="DuskServer" default="default" basedir=".">
+ <description>Builds, tests, and runs the project DuskServer.</description>
+ <import file="nbproject/build-impl.xml"/>
+ <!--
+
+ There exist several targets which are by default empty and which can be
+ used for execution of your tasks. These targets are usually executed
+ before and after some main targets. They are:
+
+ -pre-init: called before initialization of project properties
+ -post-init: called after initialization of project properties
+ -pre-compile: called before javac compilation
+ -post-compile: called after javac compilation
+ -pre-compile-single: called before javac compilation of single file
+ -post-compile-single: called after javac compilation of single file
+ -pre-compile-test: called before javac compilation of JUnit tests
+ -post-compile-test: called after javac compilation of JUnit tests
+ -pre-compile-test-single: called before javac compilation of single JUnit test
+ -post-compile-test-single: called after javac compilation of single JUunit test
+ -pre-jar: called before JAR building
+ -post-jar: called after JAR building
+ -post-clean: called after cleaning build products
+
+ (Targets beginning with '-' are not intended to be called on their own.)
+
+ Example of inserting an obfuscator after compilation could look like this:
+
+ <target name="-post-compile">
+ <obfuscate>
+ <fileset dir="${build.classes.dir}"/>
+ </obfuscate>
+ </target>
+
+ For list of available properties check the imported
+ nbproject/build-impl.xml file.
+
+
+ Another way to customize the build is by overriding existing main targets.
+ The targets of interest are:
+
+ -init-macrodef-javac: defines macro for javac compilation
+ -init-macrodef-junit: defines macro for junit execution
+ -init-macrodef-debug: defines macro for class debugging
+ -init-macrodef-java: defines macro for class execution
+ -do-jar-with-manifest: JAR building (if you are using a manifest)
+ -do-jar-without-manifest: JAR building (if you are not using a manifest)
+ run: execution of project
+ -javadoc-build: Javadoc generation
+ test-report: JUnit report generation
+
+ An example of overriding the target for project execution could look like this:
+
+ <target name="run" depends="DuskServer-impl.jar">
+ <exec dir="bin" executable="launcher.exe">
+ <arg file="${dist.jar}"/>
+ </exec>
+ </target>
+
+ Notice that the overridden target depends on the jar target and not only on
+ the compile target as the regular run target does. Again, for a list of available
+ properties which you can use, check the target you are overriding in the
+ nbproject/build-impl.xml file.
+
+ -->
+</project>
--- /dev/null
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT ***
+*** EDIT ../build.xml INSTEAD ***
+
+For the purpose of easier reading the script
+is divided into following sections:
+
+ - initialization
+ - compilation
+ - jar
+ - execution
+ - debugging
+ - javadoc
+ - test compilation
+ - test execution
+ - test debugging
+ - applet
+ - cleanup
+
+ -->
+<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="DuskServer-impl">
+ <fail message="Please build using Ant 1.8.0 or higher.">
+ <condition>
+ <not>
+ <antversion atleast="1.8.0"/>
+ </not>
+ </condition>
+ </fail>
+ <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
+ <!--
+ ======================
+ INITIALIZATION SECTION
+ ======================
+ -->
+ <target name="-pre-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="-pre-init" name="-init-private">
+ <property file="nbproject/private/config.properties"/>
+ <property file="nbproject/private/configs/${config}.properties"/>
+ <property file="nbproject/private/private.properties"/>
+ </target>
+ <target depends="-pre-init,-init-private" name="-init-user">
+ <property file="${user.properties.file}"/>
+ <!-- The two properties below are usually overridden -->
+ <!-- by the active platform. Just a fallback. -->
+ <property name="default.javac.source" value="1.4"/>
+ <property name="default.javac.target" value="1.4"/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user" name="-init-project">
+ <property file="nbproject/configs/${config}.properties"/>
+ <property file="nbproject/project.properties"/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
+ <available file="${manifest.file}" property="manifest.available"/>
+ <condition property="splashscreen.available">
+ <and>
+ <not>
+ <equals arg1="${application.splash}" arg2="" trim="true"/>
+ </not>
+ <available file="${application.splash}"/>
+ </and>
+ </condition>
+ <condition property="main.class.available">
+ <and>
+ <isset property="main.class"/>
+ <not>
+ <equals arg1="${main.class}" arg2="" trim="true"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="manifest.available+main.class">
+ <and>
+ <isset property="manifest.available"/>
+ <isset property="main.class.available"/>
+ </and>
+ </condition>
+ <condition property="do.archive">
+ <not>
+ <istrue value="${jar.archive.disabled}"/>
+ </not>
+ </condition>
+ <condition property="do.mkdist">
+ <and>
+ <isset property="do.archive"/>
+ <isset property="libs.CopyLibs.classpath"/>
+ <not>
+ <istrue value="${mkdist.disabled}"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="manifest.available+main.class+mkdist.available">
+ <and>
+ <istrue value="${manifest.available+main.class}"/>
+ <isset property="do.mkdist"/>
+ </and>
+ </condition>
+ <condition property="do.archive+manifest.available">
+ <and>
+ <isset property="manifest.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="do.archive+main.class.available">
+ <and>
+ <isset property="main.class.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="do.archive+splashscreen.available">
+ <and>
+ <isset property="splashscreen.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="do.archive+manifest.available+main.class">
+ <and>
+ <istrue value="${manifest.available+main.class}"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="manifest.available-mkdist.available">
+ <or>
+ <istrue value="${manifest.available}"/>
+ <isset property="do.mkdist"/>
+ </or>
+ </condition>
+ <condition property="manifest.available+main.class-mkdist.available">
+ <or>
+ <istrue value="${manifest.available+main.class}"/>
+ <isset property="do.mkdist"/>
+ </or>
+ </condition>
+ <condition property="have.tests">
+ <or>
+ <available file="${test.src.dir}"/>
+ </or>
+ </condition>
+ <condition property="have.sources">
+ <or>
+ <available file="${src.dir}"/>
+ </or>
+ </condition>
+ <condition property="netbeans.home+have.tests">
+ <and>
+ <isset property="netbeans.home"/>
+ <isset property="have.tests"/>
+ </and>
+ </condition>
+ <condition property="no.javadoc.preview">
+ <and>
+ <isset property="javadoc.preview"/>
+ <isfalse value="${javadoc.preview}"/>
+ </and>
+ </condition>
+ <property name="run.jvmargs" value=""/>
+ <property name="run.jvmargs.ide" value=""/>
+ <property name="javac.compilerargs" value=""/>
+ <property name="work.dir" value="${basedir}"/>
+ <condition property="no.deps">
+ <and>
+ <istrue value="${no.dependencies}"/>
+ </and>
+ </condition>
+ <property name="javac.debug" value="true"/>
+ <property name="javadoc.preview" value="true"/>
+ <property name="application.args" value=""/>
+ <property name="source.encoding" value="${file.encoding}"/>
+ <property name="runtime.encoding" value="${source.encoding}"/>
+ <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
+ <and>
+ <isset property="javadoc.encoding"/>
+ <not>
+ <equals arg1="${javadoc.encoding}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <property name="javadoc.encoding.used" value="${source.encoding}"/>
+ <property name="includes" value="**"/>
+ <property name="excludes" value=""/>
+ <property name="do.depend" value="false"/>
+ <condition property="do.depend.true">
+ <istrue value="${do.depend}"/>
+ </condition>
+ <path id="endorsed.classpath.path" path="${endorsed.classpath}"/>
+ <condition else="" property="endorsed.classpath.cmd.line.arg" value="-Xbootclasspath/p:'${toString:endorsed.classpath.path}'">
+ <length length="0" string="${endorsed.classpath}" when="greater"/>
+ </condition>
+ <condition else="false" property="jdkBug6558476">
+ <and>
+ <matches pattern="1\.[56]" string="${java.specification.version}"/>
+ <not>
+ <os family="unix"/>
+ </not>
+ </and>
+ </condition>
+ <property name="javac.fork" value="${jdkBug6558476}"/>
+ <property name="jar.index" value="false"/>
+ <property name="jar.index.metainf" value="${jar.index}"/>
+ <property name="copylibs.rebase" value="true"/>
+ <available file="${meta.inf.dir}/persistence.xml" property="has.persistence.xml"/>
+ <condition property="junit.available">
+ <or>
+ <available classname="org.junit.Test" classpath="${run.test.classpath}"/>
+ <available classname="junit.framework.Test" classpath="${run.test.classpath}"/>
+ </or>
+ </condition>
+ <condition property="testng.available">
+ <available classname="org.testng.annotations.Test" classpath="${run.test.classpath}"/>
+ </condition>
+ <condition property="junit+testng.available">
+ <and>
+ <istrue value="${junit.available}"/>
+ <istrue value="${testng.available}"/>
+ </and>
+ </condition>
+ <condition else="testng" property="testng.mode" value="mixed">
+ <istrue value="${junit+testng.available}"/>
+ </condition>
+ <condition else="" property="testng.debug.mode" value="-mixed">
+ <istrue value="${junit+testng.available}"/>
+ </condition>
+ </target>
+ <target name="-post-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
+ <fail unless="src.dir">Must set src.dir</fail>
+ <fail unless="test.src.dir">Must set test.src.dir</fail>
+ <fail unless="build.dir">Must set build.dir</fail>
+ <fail unless="dist.dir">Must set dist.dir</fail>
+ <fail unless="build.classes.dir">Must set build.classes.dir</fail>
+ <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
+ <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
+ <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
+ <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
+ <fail unless="dist.jar">Must set dist.jar</fail>
+ </target>
+ <target name="-init-macrodef-property">
+ <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute name="name"/>
+ <attribute name="value"/>
+ <sequential>
+ <property name="@{name}" value="${@{value}}"/>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors">
+ <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <attribute default="${javac.processorpath}" name="processorpath"/>
+ <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="${javac.debug}" name="debug"/>
+ <attribute default="${empty.dir}" name="sourcepath"/>
+ <attribute default="${empty.dir}" name="gensrcdir"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.dir}/empty" name="empty.dir"/>
+ <mkdir dir="${empty.dir}"/>
+ <mkdir dir="@{apgeneratedsrcdir}"/>
+ <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+ <src>
+ <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </src>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <compilerarg line="${javac.compilerargs}"/>
+ <compilerarg value="-processorpath"/>
+ <compilerarg path="@{processorpath}:${empty.dir}"/>
+ <compilerarg line="${ap.processors.internal}"/>
+ <compilerarg line="${annotation.processing.processor.options}"/>
+ <compilerarg value="-s"/>
+ <compilerarg path="@{apgeneratedsrcdir}"/>
+ <compilerarg line="${ap.proc.none.internal}"/>
+ <customize/>
+ </javac>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-ap-cmdline-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal">
+ <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <attribute default="${javac.processorpath}" name="processorpath"/>
+ <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="${javac.debug}" name="debug"/>
+ <attribute default="${empty.dir}" name="sourcepath"/>
+ <attribute default="${empty.dir}" name="gensrcdir"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.dir}/empty" name="empty.dir"/>
+ <mkdir dir="${empty.dir}"/>
+ <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+ <src>
+ <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </src>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <compilerarg line="${javac.compilerargs}"/>
+ <customize/>
+ </javac>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac">
+ <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <sequential>
+ <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ </depend>
+ </sequential>
+ </macrodef>
+ <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <sequential>
+ <fail unless="javac.includes">Must set javac.includes</fail>
+ <pathconvert pathsep="${line.separator}" property="javac.includes.binary">
+ <path>
+ <filelist dir="@{destdir}" files="${javac.includes}"/>
+ </path>
+ <globmapper from="*.java" to="*.class"/>
+ </pathconvert>
+ <tempfile deleteonexit="true" property="javac.includesfile.binary"/>
+ <echo file="${javac.includesfile.binary}" message="${javac.includes.binary}"/>
+ <delete>
+ <files includesfile="${javac.includesfile.binary}"/>
+ </delete>
+ <delete>
+ <fileset file="${javac.includesfile.binary}"/>
+ </delete>
+ </sequential>
+ </macrodef>
+ </target>
+ <target if="${junit.available}" name="-init-macrodef-junit-init">
+ <condition else="false" property="nb.junit.batch" value="true">
+ <and>
+ <istrue value="${junit.available}"/>
+ <not>
+ <isset property="test.method"/>
+ </not>
+ </and>
+ </condition>
+ <condition else="false" property="nb.junit.single" value="true">
+ <and>
+ <istrue value="${junit.available}"/>
+ <isset property="test.method"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-init-test-properties">
+ <property name="test.binaryincludes" value="<nothing>"/>
+ <property name="test.binarytestincludes" value=""/>
+ <property name="test.binaryexcludes" value=""/>
+ </target>
+ <target if="${nb.junit.single}" name="-init-macrodef-junit-single" unless="${nb.junit.batch}">
+ <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+ <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-test-properties" if="${nb.junit.batch}" name="-init-macrodef-junit-batch" unless="${nb.junit.single}">
+ <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+ <batchtest todir="${build.test.results.dir}">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
+ <filename name="${test.binarytestincludes}"/>
+ </fileset>
+ </batchtest>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit-init,-init-macrodef-junit-single, -init-macrodef-junit-batch" if="${junit.available}" name="-init-macrodef-junit"/>
+ <target if="${testng.available}" name="-init-macrodef-testng">
+ <macrodef name="testng" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <condition else="" property="testng.methods.arg" value="@{testincludes}.@{testmethods}">
+ <isset property="test.method"/>
+ </condition>
+ <union id="test.set">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ </union>
+ <taskdef classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}" name="testng"/>
+ <testng classfilesetref="test.set" failureProperty="tests.failed" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="DuskServer" testname="TestNG tests" workingDir="${work.dir}">
+ <xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/>
+ <propertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </propertyset>
+ <customize/>
+ </testng>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-test-impl">
+ <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <echo>No tests executed.</echo>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit" if="${junit.available}" name="-init-macrodef-junit-impl">
+ <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <j2seproject3:junit excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize/>
+ </j2seproject3:junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-testng" if="${testng.available}" name="-init-macrodef-testng-impl">
+ <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <j2seproject3:testng excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize/>
+ </j2seproject3:testng>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-test-impl,-init-macrodef-junit-impl,-init-macrodef-testng-impl" name="-init-macrodef-test">
+ <macrodef name="test" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <sequential>
+ <j2seproject3:test-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ </customize>
+ </j2seproject3:test-impl>
+ </sequential>
+ </macrodef>
+ </target>
+ <target if="${junit.available}" name="-init-macrodef-junit-debug" unless="${nb.junit.batch}">
+ <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+ <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-test-properties" if="${nb.junit.batch}" name="-init-macrodef-junit-debug-batch">
+ <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+ <batchtest todir="${build.test.results.dir}">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
+ <filename name="${test.binarytestincludes}"/>
+ </fileset>
+ </batchtest>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit-debug,-init-macrodef-junit-debug-batch" if="${junit.available}" name="-init-macrodef-junit-debug-impl">
+ <macrodef name="test-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <j2seproject3:junit-debug excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize/>
+ </j2seproject3:junit-debug>
+ </sequential>
+ </macrodef>
+ </target>
+ <target if="${testng.available}" name="-init-macrodef-testng-debug">
+ <macrodef name="testng-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <element name="customize2" optional="true"/>
+ <sequential>
+ <condition else="-testclass @{testClass}" property="test.class.or.method" value="-methods @{testClass}.@{testMethod}">
+ <isset property="test.method"/>
+ </condition>
+ <condition else="-suitename DuskServer -testname @{testClass} ${test.class.or.method}" property="testng.cmd.args" value="@{testClass}">
+ <matches pattern=".*\.xml" string="@{testClass}"/>
+ </condition>
+ <delete dir="${build.test.results.dir}" quiet="true"/>
+ <mkdir dir="${build.test.results.dir}"/>
+ <j2seproject3:debug classname="org.testng.TestNG" classpath="${debug.test.classpath}">
+ <customize>
+ <customize2/>
+ <jvmarg value="-ea"/>
+ <arg line="${testng.debug.mode}"/>
+ <arg line="-d ${build.test.results.dir}"/>
+ <arg line="-listener org.testng.reporters.VerboseReporter"/>
+ <arg line="${testng.cmd.args}"/>
+ </customize>
+ </j2seproject3:debug>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-testng-debug" if="${testng.available}" name="-init-macrodef-testng-debug-impl">
+ <macrodef name="testng-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <element implicit="true" name="customize2" optional="true"/>
+ <sequential>
+ <j2seproject3:testng-debug testClass="@{testClass}" testMethod="@{testMethod}">
+ <customize2/>
+ </j2seproject3:testng-debug>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit-debug-impl" if="${junit.available}" name="-init-macrodef-test-debug-junit">
+ <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <sequential>
+ <j2seproject3:test-debug-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ </customize>
+ </j2seproject3:test-debug-impl>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-testng-debug-impl" if="${testng.available}" name="-init-macrodef-test-debug-testng">
+ <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <sequential>
+ <j2seproject3:testng-debug-impl testClass="@{testClass}" testMethod="@{testMethod}">
+ <customize2>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ </customize2>
+ </j2seproject3:testng-debug-impl>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-test-debug-junit,-init-macrodef-test-debug-testng" name="-init-macrodef-test-debug"/>
+ <!--
+ pre NB7.2 profiling section; consider it deprecated
+ -->
+ <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile, -profile-init-check" if="profiler.info.jvmargs.agent" name="profile-init"/>
+ <target if="profiler.info.jvmargs.agent" name="-profile-pre-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="profiler.info.jvmargs.agent" name="-profile-post-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="profiler.info.jvmargs.agent" name="-profile-init-macrodef-profile">
+ <macrodef name="resolve">
+ <attribute name="name"/>
+ <attribute name="value"/>
+ <sequential>
+ <property name="@{name}" value="${env.@{value}}"/>
+ </sequential>
+ </macrodef>
+ <macrodef name="profile">
+ <attribute default="${main.class}" name="classname"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property environment="env"/>
+ <resolve name="profiler.current.path" value="${profiler.info.pathvar}"/>
+ <java classname="@{classname}" dir="${profiler.info.dir}" fork="true" jvm="${profiler.info.jvm}">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg value="${profiler.info.jvmargs.agent}"/>
+ <jvmarg line="${profiler.info.jvmargs}"/>
+ <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
+ <arg line="${application.args}"/>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile" if="profiler.info.jvmargs.agent" name="-profile-init-check">
+ <fail unless="profiler.info.jvm">Must set JVM to use for profiling in profiler.info.jvm</fail>
+ <fail unless="profiler.info.jvmargs.agent">Must set profiler agent JVM arguments in profiler.info.jvmargs.agent</fail>
+ </target>
+ <!--
+ end of pre NB7.2 profiling section
+ -->
+ <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
+ <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${main.class}" name="name"/>
+ <attribute default="${debug.classpath}" name="classpath"/>
+ <attribute default="" name="stopclassname"/>
+ <sequential>
+ <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ </nbjpdastart>
+ </sequential>
+ </macrodef>
+ <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${build.classes.dir}" name="dir"/>
+ <sequential>
+ <nbjpdareload>
+ <fileset dir="@{dir}" includes="${fix.classes}">
+ <include name="${fix.includes}*.class"/>
+ </fileset>
+ </nbjpdareload>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-debug-args">
+ <property name="version-output" value="java version "${ant.java.version}"/>
+ <condition property="have-jdk-older-than-1.4">
+ <or>
+ <contains string="${version-output}" substring="java version "1.0"/>
+ <contains string="${version-output}" substring="java version "1.1"/>
+ <contains string="${version-output}" substring="java version "1.2"/>
+ <contains string="${version-output}" substring="java version "1.3"/>
+ </or>
+ </condition>
+ <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
+ <istrue value="${have-jdk-older-than-1.4}"/>
+ </condition>
+ <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
+ <os family="windows"/>
+ </condition>
+ <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
+ <isset property="debug.transport"/>
+ </condition>
+ </target>
+ <target depends="-init-debug-args" name="-init-macrodef-debug">
+ <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="classname"/>
+ <attribute default="${debug.classpath}" name="classpath"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <java classname="@{classname}" dir="${work.dir}" fork="true">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+ <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-java">
+ <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${main.class}" name="classname"/>
+ <attribute default="${run.classpath}" name="classpath"/>
+ <attribute default="jvm" name="jvm"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <java classname="@{classname}" dir="${work.dir}" fork="true">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+ <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-copylibs">
+ <macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${manifest.file}" name="manifest"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <pathconvert property="run.classpath.without.build.classes.dir">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to=""/>
+ </pathconvert>
+ <pathconvert pathsep=" " property="jar.classpath">
+ <path path="${run.classpath.without.build.classes.dir}"/>
+ <chainedmapper>
+ <flattenmapper/>
+ <filtermapper>
+ <replacestring from=" " to="%20"/>
+ </filtermapper>
+ <globmapper from="*" to="lib/*"/>
+ </chainedmapper>
+ </pathconvert>
+ <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
+ <copylibs compress="${jar.compress}" index="${jar.index}" indexMetaInf="${jar.index.metainf}" jarfile="${dist.jar}" manifest="@{manifest}" rebase="${copylibs.rebase}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
+ <fileset dir="${build.classes.dir}"/>
+ <manifest>
+ <attribute name="Class-Path" value="${jar.classpath}"/>
+ <customize/>
+ </manifest>
+ </copylibs>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-presetdef-jar">
+ <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}">
+ <j2seproject1:fileset dir="${build.classes.dir}"/>
+ </jar>
+ </presetdef>
+ </target>
+ <target name="-init-ap-cmdline-properties">
+ <property name="annotation.processing.enabled" value="true"/>
+ <property name="annotation.processing.processors.list" value=""/>
+ <property name="annotation.processing.processor.options" value=""/>
+ <property name="annotation.processing.run.all.processors" value="true"/>
+ <property name="javac.processorpath" value="${javac.classpath}"/>
+ <property name="javac.test.processorpath" value="${javac.test.classpath}"/>
+ <condition property="ap.supported.internal" value="true">
+ <not>
+ <matches pattern="1\.[0-5](\..*)?" string="${javac.source}"/>
+ </not>
+ </condition>
+ </target>
+ <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-ap-cmdline-supported">
+ <condition else="" property="ap.processors.internal" value="-processor ${annotation.processing.processors.list}">
+ <isfalse value="${annotation.processing.run.all.processors}"/>
+ </condition>
+ <condition else="" property="ap.proc.none.internal" value="-proc:none">
+ <isfalse value="${annotation.processing.enabled}"/>
+ </condition>
+ </target>
+ <target depends="-init-ap-cmdline-properties,-init-ap-cmdline-supported" name="-init-ap-cmdline">
+ <property name="ap.cmd.line.internal" value=""/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-test,-init-macrodef-test-debug,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar,-init-ap-cmdline" name="init"/>
+ <!--
+ ===================
+ COMPILATION SECTION
+ ===================
+ -->
+ <target name="-deps-jar-init" unless="built-jar.properties">
+ <property location="${build.dir}/built-jar.properties" name="built-jar.properties"/>
+ <delete file="${built-jar.properties}" quiet="true"/>
+ </target>
+ <target if="already.built.jar.${basedir}" name="-warn-already-built-jar">
+ <echo level="warn" message="Cycle detected: DuskServer was already built"/>
+ </target>
+ <target depends="init,-deps-jar-init" name="deps-jar" unless="no.deps">
+ <mkdir dir="${build.dir}"/>
+ <touch file="${built-jar.properties}" verbose="false"/>
+ <property file="${built-jar.properties}" prefix="already.built.jar."/>
+ <antcall target="-warn-already-built-jar"/>
+ <propertyfile file="${built-jar.properties}">
+ <entry key="${basedir}" value=""/>
+ </propertyfile>
+ <antcall target="-maybe-call-dep">
+ <param name="call.built.properties" value="${built-jar.properties}"/>
+ <param location="${project.DuskCommon}" name="call.subproject"/>
+ <param location="${project.DuskCommon}/build.xml" name="call.script"/>
+ <param name="call.target" value="jar"/>
+ <param name="transfer.built-jar.properties" value="${built-jar.properties}"/>
+ </antcall>
+ </target>
+ <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
+ <target depends="init" name="-check-automatic-build">
+ <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
+ </target>
+ <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
+ <antcall target="clean"/>
+ </target>
+ <target depends="init,deps-jar" name="-pre-pre-compile">
+ <mkdir dir="${build.classes.dir}"/>
+ </target>
+ <target name="-pre-compile">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="do.depend.true" name="-compile-depend">
+ <pathconvert property="build.generated.subdirs">
+ <dirset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </pathconvert>
+ <j2seproject3:depend srcdir="${src.dir}:${build.generated.subdirs}"/>
+ </target>
+ <target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,-compile-depend" if="have.sources" name="-do-compile">
+ <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/>
+ <copy todir="${build.classes.dir}">
+ <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target if="has.persistence.xml" name="-copy-persistence-xml">
+ <mkdir dir="${build.classes.dir}/META-INF"/>
+ <copy todir="${build.classes.dir}/META-INF">
+ <fileset dir="${meta.inf.dir}" includes="persistence.xml orm.xml"/>
+ </copy>
+ </target>
+ <target name="-post-compile">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
+ <target name="-pre-compile-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
+ <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+ <j2seproject3:force-recompile/>
+ <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.dir}"/>
+ </target>
+ <target name="-post-compile-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
+ <!--
+ ====================
+ JAR BUILDING SECTION
+ ====================
+ -->
+ <target depends="init" name="-pre-pre-jar">
+ <dirname file="${dist.jar}" property="dist.jar.dir"/>
+ <mkdir dir="${dist.jar.dir}"/>
+ </target>
+ <target name="-pre-jar">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive" name="-do-jar-without-manifest" unless="manifest.available-mkdist.available">
+ <j2seproject1:jar/>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class-mkdist.available">
+ <j2seproject1:jar manifest="${manifest.file}"/>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
+ <j2seproject1:jar manifest="${manifest.file}">
+ <j2seproject1:manifest>
+ <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
+ </j2seproject1:manifest>
+ </j2seproject1:jar>
+ <echo level="info">To run this application from the command line without Ant, try:</echo>
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <property location="${dist.jar}" name="dist.jar.resolved"/>
+ <pathconvert property="run.classpath.with.dist.jar">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
+ </pathconvert>
+ <echo level="info">java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
+ </target>
+ <target depends="init" if="do.archive" name="-do-jar-with-libraries-create-manifest" unless="manifest.available">
+ <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
+ <touch file="${tmp.manifest.file}" verbose="false"/>
+ </target>
+ <target depends="init" if="do.archive+manifest.available" name="-do-jar-with-libraries-copy-manifest">
+ <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
+ <copy file="${manifest.file}" tofile="${tmp.manifest.file}"/>
+ </target>
+ <target depends="init,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest" if="do.archive+main.class.available" name="-do-jar-with-libraries-set-main">
+ <manifest file="${tmp.manifest.file}" mode="update">
+ <attribute name="Main-Class" value="${main.class}"/>
+ </manifest>
+ </target>
+ <target depends="init,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest" if="do.archive+splashscreen.available" name="-do-jar-with-libraries-set-splashscreen">
+ <basename file="${application.splash}" property="splashscreen.basename"/>
+ <mkdir dir="${build.classes.dir}/META-INF"/>
+ <copy failonerror="false" file="${application.splash}" todir="${build.classes.dir}/META-INF"/>
+ <manifest file="${tmp.manifest.file}" mode="update">
+ <attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/>
+ </manifest>
+ </target>
+ <target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest,-do-jar-with-libraries-set-main,-do-jar-with-libraries-set-splashscreen" if="do.mkdist" name="-do-jar-with-libraries-pack">
+ <j2seproject3:copylibs manifest="${tmp.manifest.file}"/>
+ <echo level="info">To run this application from the command line without Ant, try:</echo>
+ <property location="${dist.jar}" name="dist.jar.resolved"/>
+ <echo level="info">java -jar "${dist.jar.resolved}"</echo>
+ </target>
+ <target depends="-do-jar-with-libraries-pack" if="do.archive" name="-do-jar-with-libraries-delete-manifest">
+ <delete>
+ <fileset file="${tmp.manifest.file}"/>
+ </delete>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest,-do-jar-with-libraries-set-main,-do-jar-with-libraries-set-splashscreen,-do-jar-with-libraries-pack,-do-jar-with-libraries-delete-manifest" name="-do-jar-with-libraries"/>
+ <target name="-post-jar">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
+ <!--
+ =================
+ EXECUTION SECTION
+ =================
+ -->
+ <target depends="init,compile" description="Run a main class." name="run">
+ <j2seproject1:java>
+ <customize>
+ <arg line="${application.args}"/>
+ </customize>
+ </j2seproject1:java>
+ </target>
+ <target name="-do-not-recompile">
+ <property name="javac.includes.binary" value=""/>
+ </target>
+ <target depends="init,compile-single" name="run-single">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <j2seproject1:java classname="${run.class}"/>
+ </target>
+ <target depends="init,compile-test-single" name="run-test-with-main">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/>
+ </target>
+ <!--
+ =================
+ DEBUGGING SECTION
+ =================
+ -->
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger">
+ <j2seproject1:nbjpdastart name="${debug.class}"/>
+ </target>
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger-main-test">
+ <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${debug.class}"/>
+ </target>
+ <target depends="init,compile" name="-debug-start-debuggee">
+ <j2seproject3:debug>
+ <customize>
+ <arg line="${application.args}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
+ <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
+ </target>
+ <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
+ <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
+ <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+ <j2seproject3:debug classname="${debug.class}"/>
+ </target>
+ <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
+ <target depends="init,compile-test-single" if="netbeans.home" name="-debug-start-debuggee-main-test">
+ <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+ <j2seproject3:debug classname="${debug.class}" classpath="${debug.test.classpath}"/>
+ </target>
+ <target depends="init,compile-test-single,-debug-start-debugger-main-test,-debug-start-debuggee-main-test" if="netbeans.home" name="debug-test-with-main"/>
+ <target depends="init" name="-pre-debug-fix">
+ <fail unless="fix.includes">Must set fix.includes</fail>
+ <property name="javac.includes" value="${fix.includes}.java"/>
+ </target>
+ <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
+ <j2seproject1:nbjpdareload/>
+ </target>
+ <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
+ <!--
+ =================
+ PROFILING SECTION
+ =================
+ -->
+ <!--
+ pre NB7.2 profiler integration
+ -->
+ <target depends="profile-init,compile" description="Profile a project in the IDE." if="profiler.info.jvmargs.agent" name="-profile-pre72">
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <profile/>
+ </target>
+ <target depends="profile-init,compile-single" description="Profile a selected class in the IDE." if="profiler.info.jvmargs.agent" name="-profile-single-pre72">
+ <fail unless="profile.class">Must select one file in the IDE or set profile.class</fail>
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <profile classname="${profile.class}"/>
+ </target>
+ <target depends="profile-init,compile-single" if="profiler.info.jvmargs.agent" name="-profile-applet-pre72">
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <profile classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </profile>
+ </target>
+ <target depends="profile-init,compile-test-single" if="profiler.info.jvmargs.agent" name="-profile-test-single-pre72">
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <junit dir="${profiler.info.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" jvm="${profiler.info.jvm}" showoutput="true">
+ <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
+ <jvmarg value="${profiler.info.jvmargs.agent}"/>
+ <jvmarg line="${profiler.info.jvmargs}"/>
+ <test name="${profile.class}"/>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ </junit>
+ </target>
+ <!--
+ end of pre NB72 profiling section
+ -->
+ <target if="netbeans.home" name="-profile-check">
+ <condition property="profiler.configured">
+ <or>
+ <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-agentpath:"/>
+ <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-javaagent:"/>
+ </or>
+ </condition>
+ </target>
+ <target depends="-profile-check,-profile-pre72" description="Profile a project in the IDE." if="profiler.configured" name="profile" unless="profiler.info.jvmargs.agent">
+ <startprofiler/>
+ <antcall target="run"/>
+ </target>
+ <target depends="-profile-check,-profile-single-pre72" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-single" unless="profiler.info.jvmargs.agent">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <startprofiler/>
+ <antcall target="run-single"/>
+ </target>
+ <target depends="-profile-test-single-pre72" description="Profile a selected test in the IDE." name="profile-test-single"/>
+ <target depends="-profile-check" description="Profile a selected test in the IDE." if="profiler.configured" name="profile-test" unless="profiler.info.jvmargs">
+ <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+ <startprofiler/>
+ <antcall target="test-single"/>
+ </target>
+ <target depends="-profile-check" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-test-with-main">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <startprofiler/>
+ <antcal target="run-test-with-main"/>
+ </target>
+ <target depends="-profile-check,-profile-applet-pre72" if="profiler.configured" name="profile-applet" unless="profiler.info.jvmargs.agent">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <startprofiler/>
+ <antcall target="run-applet"/>
+ </target>
+ <!--
+ ===============
+ JAVADOC SECTION
+ ===============
+ -->
+ <target depends="init" if="have.sources" name="-javadoc-build">
+ <mkdir dir="${dist.javadoc.dir}"/>
+ <condition else="" property="javadoc.endorsed.classpath.cmd.line.arg" value="-J${endorsed.classpath.cmd.line.arg}">
+ <and>
+ <isset property="endorsed.classpath.cmd.line.arg"/>
+ <not>
+ <equals arg1="${endorsed.classpath.cmd.line.arg}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
+ <classpath>
+ <path path="${javac.classpath}"/>
+ </classpath>
+ <fileset dir="${src.dir}" excludes="*.java,${excludes}" includes="${includes}">
+ <filename name="**/*.java"/>
+ </fileset>
+ <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="**/*.java"/>
+ <exclude name="*.java"/>
+ </fileset>
+ <arg line="${javadoc.endorsed.classpath.cmd.line.arg}"/>
+ </javadoc>
+ <copy todir="${dist.javadoc.dir}">
+ <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
+ <filename name="**/doc-files/**"/>
+ </fileset>
+ <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="**/doc-files/**"/>
+ </fileset>
+ </copy>
+ </target>
+ <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
+ <nbbrowse file="${dist.javadoc.dir}/index.html"/>
+ </target>
+ <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
+ <!--
+ =========================
+ TEST COMPILATION SECTION
+ =========================
+ -->
+ <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
+ <mkdir dir="${build.test.classes.dir}"/>
+ </target>
+ <target name="-pre-compile-test">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="do.depend.true" name="-compile-test-depend">
+ <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
+ </target>
+ <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
+ <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" processorpath="${javac.test.processorpath}" srcdir="${test.src.dir}"/>
+ <copy todir="${build.test.classes.dir}">
+ <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile-test">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
+ <target name="-pre-compile-test-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
+ <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+ <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
+ <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" processorpath="${javac.test.processorpath}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
+ <copy todir="${build.test.classes.dir}">
+ <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile-test-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
+ <!--
+ =======================
+ TEST EXECUTION SECTION
+ =======================
+ -->
+ <target depends="init" if="have.tests" name="-pre-test-run">
+ <mkdir dir="${build.test.results.dir}"/>
+ </target>
+ <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
+ <j2seproject3:test testincludes="**/*Test.java"/>
+ </target>
+ <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init" if="have.tests" name="test-report"/>
+ <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
+ <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
+ <target depends="init" if="have.tests" name="-pre-test-run-single">
+ <mkdir dir="${build.test.results.dir}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
+ <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+ <j2seproject3:test excludes="" includes="${test.includes}" testincludes="${test.includes}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single-method">
+ <fail unless="test.class">Must select some files in the IDE or set test.class</fail>
+ <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
+ <j2seproject3:test excludes="" includes="${javac.includes}" testincludes="${test.class}" testmethods="${test.method}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method" if="have.tests" name="-post-test-run-single-method">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method,-post-test-run-single-method" description="Run single unit test." name="test-single-method"/>
+ <!--
+ =======================
+ TEST DEBUGGING SECTION
+ =======================
+ -->
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test">
+ <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+ <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testincludes="${javac.includes}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test-method">
+ <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+ <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
+ <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testMethod="${test.method}" testincludes="${test.class}" testmethods="${test.method}"/>
+ </target>
+ <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
+ <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
+ </target>
+ <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
+ <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test-method" name="debug-test-method"/>
+ <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
+ <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
+ </target>
+ <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
+ <!--
+ =========================
+ APPLET EXECUTION SECTION
+ =========================
+ -->
+ <target depends="init,compile-single" name="run-applet">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <j2seproject1:java classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </j2seproject1:java>
+ </target>
+ <!--
+ =========================
+ APPLET DEBUGGING SECTION
+ =========================
+ -->
+ <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <j2seproject3:debug classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
+ <!--
+ ===============
+ CLEANUP SECTION
+ ===============
+ -->
+ <target name="-deps-clean-init" unless="built-clean.properties">
+ <property location="${build.dir}/built-clean.properties" name="built-clean.properties"/>
+ <delete file="${built-clean.properties}" quiet="true"/>
+ </target>
+ <target if="already.built.clean.${basedir}" name="-warn-already-built-clean">
+ <echo level="warn" message="Cycle detected: DuskServer was already built"/>
+ </target>
+ <target depends="init,-deps-clean-init" name="deps-clean" unless="no.deps">
+ <mkdir dir="${build.dir}"/>
+ <touch file="${built-clean.properties}" verbose="false"/>
+ <property file="${built-clean.properties}" prefix="already.built.clean."/>
+ <antcall target="-warn-already-built-clean"/>
+ <propertyfile file="${built-clean.properties}">
+ <entry key="${basedir}" value=""/>
+ </propertyfile>
+ <antcall target="-maybe-call-dep">
+ <param name="call.built.properties" value="${built-clean.properties}"/>
+ <param location="${project.DuskCommon}" name="call.subproject"/>
+ <param location="${project.DuskCommon}/build.xml" name="call.script"/>
+ <param name="call.target" value="clean"/>
+ <param name="transfer.built-clean.properties" value="${built-clean.properties}"/>
+ </antcall>
+ </target>
+ <target depends="init" name="-do-clean">
+ <delete dir="${build.dir}"/>
+ <delete dir="${dist.dir}" followsymlinks="false" includeemptydirs="true"/>
+ </target>
+ <target name="-post-clean">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
+ <target name="-check-call-dep">
+ <property file="${call.built.properties}" prefix="already.built."/>
+ <condition property="should.call.dep">
+ <and>
+ <not>
+ <isset property="already.built.${call.subproject}"/>
+ </not>
+ <available file="${call.script}"/>
+ </and>
+ </condition>
+ </target>
+ <target depends="-check-call-dep" if="should.call.dep" name="-maybe-call-dep">
+ <ant antfile="${call.script}" inheritall="false" target="${call.target}">
+ <propertyset>
+ <propertyref prefix="transfer."/>
+ <mapper from="transfer.*" to="*" type="glob"/>
+ </propertyset>
+ </ant>
+ </target>
+</project>
--- /dev/null
+build.xml.data.CRC32=d4396c02
+build.xml.script.CRC32=b70baa11
+build.xml.stylesheet.CRC32=28e38971@1.56.1.46
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=d4396c02
+nbproject/build-impl.xml.script.CRC32=6bdc7120
+nbproject/build-impl.xml.stylesheet.CRC32=c6d2a60f@1.56.1.46
--- /dev/null
+application.title=DuskServer
+application.vendor=Michael Zucchi
+endorsed.classpath=
+project.license=dusk
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.processors.list=
+annotation.processing.run.all.processors=true
+annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/DuskServer.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+includes=**
+jar.compress=false
+javac.classpath=\
+ ${reference.DuskCommon.jar}
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.processorpath=\
+ ${javac.classpath}
+javac.source=1.7
+javac.target=1.7
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+javac.test.processorpath=\
+ ${javac.test.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+main.class=duskz.server.DuskServer
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+mkdist.disabled=false
+platform.active=default_platform
+project.DuskCommon=../DuskCommon
+reference.DuskCommon.jar=${project.DuskCommon}/dist/DuskCommon.jar
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project.
+# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
+# To set system properties for unit tests define test-sys-prop.name=value:
+run.jvmargs=
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.java.j2seproject</type>
+ <configuration>
+ <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
+ <name>DuskServer</name>
+ <source-roots>
+ <root id="src.dir"/>
+ </source-roots>
+ <test-roots>
+ <root id="test.src.dir"/>
+ </test-roots>
+ </data>
+ <references xmlns="http://www.netbeans.org/ns/ant-project-references/1">
+ <reference>
+ <foreign-project>DuskCommon</foreign-project>
+ <artifact-type>jar</artifact-type>
+ <script>build.xml</script>
+ <target>jar</target>
+ <clean-target>clean</clean-target>
+ <id>jar</id>
+ </reference>
+ </references>
+ </configuration>
+</project>
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.io;
+
+import duskz.server.entity.TileMap;
+import duskz.io.tiled.Data;
+import duskz.io.tiled.Image;
+import duskz.io.tiled.Layer;
+import duskz.io.tiled.Map;
+import duskz.io.tiled.Property;
+import duskz.io.tiled.Tile;
+import duskz.io.tiled.Tileset;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.StringReader;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+import javax.imageio.ImageIO;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.MemoryCacheImageInputStream;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+/**
+ * Tiled loader/converter. This is only experimental at this stage.
+ *
+ * @author notzed
+ */
+public class Tiled {
+
+ static byte[] map64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(Charset.forName("US-ASCII"));
+ static byte[] unmap64 = new byte[256];
+
+ static {
+ for (int i = 0; i < 256; i++)
+ unmap64[i] = -1;
+ for (int i = 0; i < 64; i++) {
+ unmap64[map64[i]] = (byte) i;
+ }
+ }
+ // gzip and base64 result
+
+ static String encodeArray(byte[] data) throws IOException {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ GZIPOutputStream gz = new GZIPOutputStream(os);
+
+ gz.write(data);
+ gz.close();
+ return encodeBytes(os.toByteArray());
+ }
+
+ static InputStream decodeArray(String s) throws IOException {
+ ByteArrayInputStream is = new ByteArrayInputStream(decodeBytes(s));
+ GZIPInputStream gz = new GZIPInputStream(is);
+
+ return gz;
+ }
+
+ static int getCode(StringReader sr) throws IOException {
+ int v;
+
+ do {
+ v = sr.read();
+ if (v == -1)
+ return -1;
+ if (v == '=')
+ return -1;
+ v = unmap64[v];
+ } while (v == -1);
+ return v;
+ }
+
+ static byte[] decodeBytes(String s) throws IOException {
+ ByteBuffer dec = ByteBuffer.allocate(s.length());
+ StringReader sr = new StringReader(s);
+ int a, b, c, d;
+ do {
+ a = getCode(sr);
+ b = getCode(sr);
+ c = getCode(sr);
+ d = getCode(sr);
+
+ if (a == -1) {
+ // Truncated input
+ } else if (b == -1) {
+ // Truncated input
+ } else if (c == -1) {
+ // one encoded value
+ dec.put((byte) ((a << 2) | (b >> 4)));
+ } else if (d == -1) {
+ // 2 encoded valus
+ dec.put((byte) ((a << 2) | (b >> 4)));
+ dec.put((byte) ((b << 4) | (c >> 2)));
+ } else {
+ dec.put((byte) ((a << 2) | (b >> 4)));
+ dec.put((byte) ((b << 4) | (c >> 2)));
+ dec.put((byte) ((c << 6) | d));
+ }
+ } while (d != -1);
+
+ return Arrays.copyOf(dec.array(), dec.position());
+ }
+
+ static String encodeBytes(byte[] bytes) {
+ // Convert to base64
+ ByteBuffer enc = ByteBuffer.allocate(bytes.length * 4);
+ int i = 0;
+ int line = 0;
+ while (i < bytes.length) {
+ int a = bytes[i++];
+ int b = 0;
+ int c = 0;
+ int count = 2;
+
+ if (i < bytes.length) {
+ b = bytes[i++];
+ count = 3;
+ }
+ if (i < bytes.length) {
+ c = bytes[i++];
+ count = 4;
+ }
+
+ enc.put(map64[(a >> 2) & 63]);
+ enc.put(map64[((a << 4) & 0x30) | ((b >> 4) & 15)]);
+ if (count > 2)
+ enc.put(map64[((b << 2) & 0x3c) | ((c >> 6) & 3)]);
+ else
+ enc.put((byte) '=');
+ if (count > 3)
+ enc.put(map64[c & 63]);
+ else
+ enc.put((byte) '=');
+
+ line += 4;
+ if (line >= 72) {
+ enc.put((byte) 10);
+ line = 0;
+ }
+ }
+ return new String(enc.array(), 0, enc.position(), Charset.forName("us-ascii"));
+ }
+
+ static String encodeImage(BufferedImage image) throws IOException {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ ImageIO.write(image, "png", os);
+ os.close();
+ return encodeBytes(os.toByteArray());
+ }
+
+ static BufferedImage decodeImage(String enc) throws IOException {
+ byte[] data = decodeBytes(enc);
+ InputStream is = new ByteArrayInputStream(data);
+
+ return ImageIO.read(is);
+ }
+
+ static void testexport() throws IOException {
+ File path = new File("/home/notzed/src/DuskRPG/DuskFiles/Dusk2.7.3/shortmap");
+
+ TileMap map = TileMap.loadMap(path, TileMap.FORMAT_SHORT);
+ int width = map.getCols();
+ int height = map.getRows();
+ int len = width * height;
+
+
+ System.out.println("Map size: " + width + "," + height);
+
+ duskz.io.tiled.Map tmap = new duskz.io.tiled.Map();
+
+ tmap.setWidth(width);
+ tmap.setHeight(height);
+ tmap.setOrientation("orthogonal");
+ tmap.setVersion("1.0");
+ tmap.setTilewidth(32);
+ tmap.setTileheight(32);
+
+ Tileset tset = new Tileset();
+ tmap.getTileset().add(tset);
+
+ tset.setTileheight(32);
+ tset.setTilewidth(32);
+ tset.setFirstgid(0);
+ tset.setName("dusk-map");
+
+ // Add tile set
+ BufferedImage tiles = ImageIO.read(new File("/home/notzed/src/DuskRPG/DuskFiles/Dusk2.7.3/www/rc/somedusk/images/map.png"));
+ int tileWidth = 32;
+ int tileHeight = 32;
+ int imageWidth = tiles.getWidth();
+ for (int x = 0; x * tileWidth < imageWidth; x++) {
+ BufferedImage tile = tiles.getSubimage(x * tileWidth, 0, tileWidth, tileHeight);
+
+ Image timage = new Image();
+ Data idata = new Data();
+
+ idata.setEncoding("base64");
+ idata.setvalue(encodeImage(tile));
+ timage.setData(idata);
+ timage.setFormat("png");
+
+ Tile ttile = new Tile();
+ ttile.setId(x);
+ ttile.setImage(timage);
+
+ tset.getTile().add(ttile);
+ }
+
+ // Add layer
+ Layer layer = new Layer();
+
+ tmap.getLayerOrObjectgroup().add(layer);
+
+ layer.setName("base");
+ layer.setVisible(1);
+ layer.setOpacity(1);
+ layer.setWidth(map.getCols());
+ layer.setHeight(map.getRows());
+
+ Data d = new Data();
+
+ layer.setData(d);
+
+ d.setCompression("gzip");
+ d.setEncoding("base64");
+
+ // First convert to ints
+ ByteBuffer bb = ByteBuffer.allocate(len * 4).order(ByteOrder.LITTLE_ENDIAN);
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ bb.putInt(map.getTile(x, y));
+ }
+ }
+ bb.rewind();
+
+ d.setvalue(encodeArray(bb.array()));
+ //d.setvalue("dummy");
+
+ try {
+ JAXBContext jc = JAXBContext.newInstance(Map.class);
+ //Unmarshaller u = jc.createUnmarshaller();
+ //Object element = u.unmarshal(new File("foo.xml"));
+ Marshaller m = jc.createMarshaller();
+
+ m.setProperty("jaxb.formatted.output", true);
+
+
+ m.marshal(tmap, new File("/home/notzed/tiled-test.tmx"));
+
+ } catch (JAXBException ex) {
+ Logger.getLogger(Tiled.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ System.out.println("done");
+
+ }
+
+ static class TileInfo {
+
+ int id;
+ // Script names
+ String move;
+ String see;
+ String action;
+ }
+
+ static void testimport(File src, File dst) throws IOException {
+ try {
+ JAXBContext jc = JAXBContext.newInstance(Map.class);
+ Unmarshaller u = jc.createUnmarshaller();
+ Map tmap = (Map) u.unmarshal(src);
+
+ System.out.println("Loaded map size: " + tmap.getWidth() + "x" + tmap.getHeight());
+
+ Manifest man = new Manifest();
+
+ List<TileInfo> tileInfo = new ArrayList<>();
+ int tid = 0;
+
+ // Create manifest entires for tileset
+ if (true) {
+ int setid = 0;
+
+ Attributes a = new Attributes();
+
+ for (Tileset ts : tmap.getTileset()) {
+ int gid0 = ts.getFirstgid();
+
+ if (ts.getSource() != null) {
+ URI uri = src.toURI().resolve(ts.getSource());
+
+ ts = (Tileset) u.unmarshal(new File(uri));
+ }
+ if (!ts.getTile().isEmpty()) {
+ Tile tt = ts.getTile().get(0);
+ BufferedImage image = decodeImage(tt.getImage().getData().getvalue());
+
+ int twidth = image.getWidth();
+ int theight = image.getHeight();
+
+ a.putValue(setid + "_name", ts.getName());
+ a.putValue(setid + "_gid", String.valueOf(gid0));
+ a.putValue(setid + "_count", String.valueOf(ts.getTile().size()));
+ a.putValue(setid + "_source", "tiles/tiles_" + gid0 + ".png");
+ a.putValue(setid + "_width", String.valueOf(twidth));
+ a.putValue(setid + "_height", String.valueOf(theight));
+ setid++;
+
+ tid = 0;
+ // Add itle info
+ for (Tile ttile : ts.getTile()) {
+ TileInfo ti = new TileInfo();
+
+ // assume tid.id == tile id?
+ if (tid != ttile.getId()) {
+ System.out.println("shit tile id mismatch: " + tid + "!= " + ttile.getId());
+ }
+ ti.id = gid0 + tid;
+ tid++;
+
+ if (ttile.getProperties() != null) {
+ for (Property p : ttile.getProperties().getProperty()) {
+ switch (p.getName()) {
+ case "move":
+ ti.move = p.getValue();
+ break;
+ case "see":
+ ti.see = p.getValue();
+ break;
+ case "action":
+ ti.action = p.getValue();
+ break;
+ }
+ }
+ }
+ if (ti.move != null && ti.see == null) {
+ ti.see = ti.move;
+ }
+ tileInfo.add(ti);
+ }
+
+ }
+
+ }
+ a.putValue("count", String.valueOf(setid));
+ man.getEntries().put("tilesets", a);
+ }
+
+ JarOutputStream jos = new JarOutputStream(new FileOutputStream(dst), man);
+ {
+ String[] dirs = {"maps/", "tiles/"};
+ for (String d : dirs) {
+ JarEntry je = new JarEntry(d);
+ jos.putNextEntry(je);
+ jos.closeEntry();
+ }
+ }
+
+ TileMap map = new TileMap(tmap.getWidth(), tmap.getHeight());
+
+ int lid = 0;
+
+ for (Object o : tmap.getLayerOrObjectgroup()) {
+ if (o instanceof Layer) {
+ Layer l = (Layer) o;
+
+ // FIXME: remap map?
+ //l.getData().getvalue();
+
+ // encoding blah blah
+
+ InputStream is = decodeArray(l.getData().getvalue());
+ ImageInputStream dis = new MemoryCacheImageInputStream(is);
+
+ dis.setByteOrder(ByteOrder.LITTLE_ENDIAN);
+
+ // Convert to shorts
+ JarEntry je = new JarEntry("maps/0-" + lid + "-" + l.getName());
+ jos.putNextEntry(je);
+
+ DataOutputStream dos = new DataOutputStream(jos);
+ dos.writeInt(l.getWidth());
+ dos.writeInt(l.getHeight());
+ for (int y = 0; y < l.getHeight(); y++) {
+ for (int x = 0; x < l.getWidth(); x++) {
+ int t = dis.readInt();
+ dos.writeShort(t);
+ //System.out.printf("%3d\n", t);
+ }
+ }
+ dos.flush();
+ //dos.close();
+
+ jos.closeEntry();
+ }
+ }
+
+ // Add tile script names
+ {
+ JarEntry je = new JarEntry("tiles/scripts");
+ jos.putNextEntry(je);
+ PrintStream ps = new PrintStream(jos);
+ for (TileInfo ti : tileInfo) {
+ if (ti.move != null && !ti.move.equals("false")) {
+ ps.format("move.%d=%s\n", ti.id, ti.move);
+ }
+ if (ti.see != null && !ti.see.equals("false")) {
+ ps.format("see.%d=%s\n", ti.id, ti.see);
+ }
+ if (ti.action != null) {
+ ps.format("action.%d=%s\n", ti.id, ti.action);
+ }
+ }
+ ps.flush();
+ jos.closeEntry();
+ }
+
+ // Build tileset manifest - nope in manifest
+ if (false) {
+ int setid = 0;
+ JarEntry je = new JarEntry("tiles/manifest");
+ jos.putNextEntry(je);
+ PrintStream ps = new PrintStream(jos);
+ for (Tileset ts : tmap.getTileset()) {
+ int gid0 = ts.getFirstgid();
+
+ if (ts.getSource() != null) {
+ URI uri = src.toURI().resolve(ts.getSource());
+
+ ts = (Tileset) u.unmarshal(new File(uri));
+ }
+ if (!ts.getTile().isEmpty()) {
+ Tile tt = ts.getTile().get(0);
+ BufferedImage image = decodeImage(tt.getImage().getData().getvalue());
+
+ int twidth = image.getWidth();
+ int theight = image.getHeight();
+
+ ps.format("tiles.%d.name=%s\n", setid, ts.getName());
+ ps.format("tiles.%s.width=%d\n", setid, twidth);
+ ps.format("tiles.%s.height=%d\n", setid, theight);
+ ps.format("tiles.%s.source=tiles-%d.png\n", setid, gid0);
+ ps.format("tiles.%s.firstGid=%d\n", setid, gid0);
+ setid++;
+ }
+
+ }
+ ps.format("tiles.count=%d\n", setid);
+ ps.flush();
+ jos.closeEntry();
+ }
+
+ for (Tileset ts : tmap.getTileset()) {
+ int gid0 = ts.getFirstgid();
+
+ if (ts.getSource() != null) {
+ URI uri = src.toURI().resolve(ts.getSource());
+
+ ts = (Tileset) u.unmarshal(new File(uri));
+ }
+
+
+ int twidth = 0, theight = 0;
+ BufferedImage tmp = null;
+ Graphics2D gg = null;
+
+ System.out.println("found tileset: " + ts.getName());
+
+ int ntiles = ts.getTile().size();
+
+ int i = 0;
+ for (Tile tt : ts.getTile()) {
+ BufferedImage image = decodeImage(tt.getImage().getData().getvalue());
+
+ if (tmp == null) {
+ twidth = image.getWidth();
+ theight = image.getHeight();
+ tmp = new BufferedImage(ntiles * twidth, theight, BufferedImage.TYPE_INT_ARGB);
+ gg = tmp.createGraphics();
+ } else if (image.getWidth() != twidth || image.getHeight() != theight) {
+ System.out.println("Image tiles differ in size\n");
+ }
+
+ gg.drawImage(image, (i++) * twidth, 0, null);
+ }
+
+ if (tmp != null) {
+ //ImageIO.write(tmp, "png", new File("/home/notzed/tiled-tiles-" + twidth + "x" + theight + ".png"));
+
+ JarEntry ze = new JarEntry("tiles/tiles_" + gid0 + ".png");
+ jos.putNextEntry(ze);
+ ImageIO.write(tmp, "png", jos);
+ jos.closeEntry();
+ }
+ }
+ jos.close();
+
+ } catch (JAXBException ex) {
+ Logger.getLogger(Tiled.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ // test load/save itled format map
+
+ public static void main(String[] args) throws IOException {
+ testimport(new File("/home/notzed/house.tmx"),
+ new File("/home/notzed/house.jar"));
+ //testexport();
+ }
+}
--- /dev/null
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2013.02.27 at 01:07:39 PM CST
+//
+
+
+package duskz.io.tiled;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+
+/**
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "value"
+})
+@XmlRootElement(name = "data")
+public class Data {
+
+ @XmlAttribute(name = "encoding")
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String encoding;
+ @XmlAttribute(name = "compression")
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String compression;
+ @XmlValue
+ protected String value;
+
+ /**
+ * Gets the value of the encoding property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getEncoding() {
+ return encoding;
+ }
+
+ /**
+ * Sets the value of the encoding property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setEncoding(String value) {
+ this.encoding = value;
+ }
+
+ /**
+ * Gets the value of the compression property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getCompression() {
+ return compression;
+ }
+
+ /**
+ * Sets the value of the compression property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setCompression(String value) {
+ this.compression = value;
+ }
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getvalue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setvalue(String value) {
+ this.value = value;
+ }
+
+}
--- /dev/null
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2013.02.27 at 01:07:39 PM CST
+//
+
+
+package duskz.io.tiled;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+
+/**
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "data"
+})
+@XmlRootElement(name = "image")
+public class Image {
+
+ @XmlAttribute(name = "format")
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String format;
+ @XmlAttribute(name = "id")
+ protected String id;
+ @XmlAttribute(name = "source")
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String source;
+ @XmlAttribute(name = "trans")
+ protected String trans;
+ protected Data data;
+
+ /**
+ * Gets the value of the format property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getFormat() {
+ return format;
+ }
+
+ /**
+ * Sets the value of the format property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setFormat(String value) {
+ this.format = value;
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+
+ /**
+ * Gets the value of the source property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getSource() {
+ return source;
+ }
+
+ /**
+ * Sets the value of the source property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setSource(String value) {
+ this.source = value;
+ }
+
+ /**
+ * Gets the value of the trans property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getTrans() {
+ return trans;
+ }
+
+ /**
+ * Sets the value of the trans property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setTrans(String value) {
+ this.trans = value;
+ }
+
+ /**
+ * Gets the value of the data property.
+ *
+ * @return
+ * possible object is
+ * {@link Data }
+ *
+ */
+ public Data getData() {
+ return data;
+ }
+
+ /**
+ * Sets the value of the data property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Data }
+ *
+ */
+ public void setData(Data value) {
+ this.data = value;
+ }
+
+}
--- /dev/null
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2013.02.27 at 01:07:39 PM CST
+//
+
+
+package duskz.io.tiled;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
+import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+
+/**
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "properties",
+ "data"
+})
+@XmlRootElement(name = "layer")
+public class Layer {
+
+ @XmlAttribute(name = "name", required = true)
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String name;
+ @XmlAttribute(name = "width", required = true)
+ protected int width;
+ @XmlAttribute(name = "height", required = true)
+ protected int height;
+ @XmlAttribute(name = "x")
+ protected int x;
+ @XmlAttribute(name = "y")
+ protected int y;
+ @XmlAttribute(name = "opacity")
+ protected float opacity;
+ @XmlAttribute(name = "visible")
+ protected int visible;
+ protected Properties properties;
+ @XmlElement(required = true)
+ protected Data data;
+
+ /**
+ * Gets the value of the name property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setName(String value) {
+ this.name = value;
+ }
+
+ /**
+ * Gets the value of the width property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Sets the value of the width property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setWidth(int value) {
+ this.width = value;
+ }
+
+ /**
+ * Gets the value of the height property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Sets the value of the height property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setHeight(int value) {
+ this.height = value;
+ }
+
+ /**
+ * Gets the value of the x property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getX() {
+ return x;
+ }
+
+ /**
+ * Sets the value of the x property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setX(int value) {
+ this.x = value;
+ }
+
+ /**
+ * Gets the value of the y property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getY() {
+ return y;
+ }
+
+ /**
+ * Sets the value of the y property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setY(int value) {
+ this.y = value;
+ }
+
+ /**
+ * Gets the value of the opacity property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public float getOpacity() {
+ return opacity;
+ }
+
+ /**
+ * Sets the value of the opacity property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setOpacity(float value) {
+ this.opacity = value;
+ }
+
+ /**
+ * Gets the value of the visible property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getVisible() {
+ return visible;
+ }
+
+ /**
+ * Sets the value of the visible property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setVisible(int value) {
+ this.visible = value;
+ }
+
+ /**
+ * Gets the value of the properties property.
+ *
+ * @return
+ * possible object is
+ * {@link Properties }
+ *
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Sets the value of the properties property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Properties }
+ *
+ */
+ public void setProperties(Properties value) {
+ this.properties = value;
+ }
+
+ /**
+ * Gets the value of the data property.
+ *
+ * @return
+ * possible object is
+ * {@link Data }
+ *
+ */
+ public Data getData() {
+ return data;
+ }
+
+ /**
+ * Sets the value of the data property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Data }
+ *
+ */
+ public void setData(Data value) {
+ this.data = value;
+ }
+
+}
--- /dev/null
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2013.02.27 at 01:07:39 PM CST
+//
+
+
+package duskz.io.tiled;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
+import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+
+/**
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "properties",
+ "tileset",
+ "layerOrObjectgroup"
+})
+@XmlRootElement(name = "map")
+public class Map {
+
+ @XmlAttribute(name = "xmlns")
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String xmlns;
+ @XmlAttribute(name = "xmlns:xsi")
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String xmlnsXsi;
+ @XmlAttribute(name = "xsi:schemaLocation")
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String xsiSchemaLocation;
+ @XmlAttribute(name = "version", required = true)
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String version;
+ @XmlAttribute(name = "orientation", required = true)
+ @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
+ protected String orientation;
+ @XmlAttribute(name = "width", required = true)
+ protected int width;
+ @XmlAttribute(name = "height", required = true)
+ protected int height;
+ @XmlAttribute(name = "tilewidth", required = true)
+ protected int tilewidth;
+ @XmlAttribute(name = "tileheight", required = true)
+ protected int tileheight;
+ protected Properties properties;
+ protected List<Tileset> tileset;
+ @XmlElements({
+ @XmlElement(name = "layer", type = Layer.class),
+ @XmlElement(name = "objectgroup", type = Objectgroup.class)
+ })
+ protected List<java.lang.Object> layerOrObjectgroup;
+
+ /**
+ * Gets the value of the xmlns property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getXmlns() {
+ return xmlns;
+ }
+
+ /**
+ * Sets the value of the xmlns property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setXmlns(String value) {
+ this.xmlns = value;
+ }
+
+ /**
+ * Gets the value of the xmlnsXsi property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getXmlnsXsi() {
+ return xmlnsXsi;
+ }
+
+ /**
+ * Sets the value of the xmlnsXsi property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setXmlnsXsi(String value) {
+ this.xmlnsXsi = value;
+ }
+
+ /**
+ * Gets the value of the xsiSchemaLocation property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getXsiSchemaLocation() {
+ return xsiSchemaLocation;
+ }
+
+ /**
+ * Sets the value of the xsiSchemaLocation property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setXsiSchemaLocation(String value) {
+ this.xsiSchemaLocation = value;
+ }
+
+ /**
+ * Gets the value of the version property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * Sets the value of the version property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setVersion(String value) {
+ this.version = value;
+ }
+
+ /**
+ * Gets the value of the orientation property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getOrientation() {
+ return orientation;
+ }
+
+ /**
+ * Sets the value of the orientation property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setOrientation(String value) {
+ this.orientation = value;
+ }
+
+ /**
+ * Gets the value of the width property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Sets the value of the width property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setWidth(int value) {
+ this.width = value;
+ }
+
+ /**
+ * Gets the value of the height property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Sets the value of the height property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setHeight(int value) {
+ this.height = value;
+ }
+
+ /**
+ * Gets the value of the tilewidth property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getTilewidth() {
+ return tilewidth;
+ }
+
+ /**
+ * Sets the value of the tilewidth property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setTilewidth(int value) {
+ this.tilewidth = value;
+ }
+
+ /**
+ * Gets the value of the tileheight property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getTileheight() {
+ return tileheight;
+ }
+
+ /**
+ * Sets the value of the tileheight property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setTileheight(int value) {
+ this.tileheight = value;
+ }
+
+ /**
+ * Gets the value of the properties property.
+ *
+ * @return
+ * possible object is
+ * {@link Properties }
+ *
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Sets the value of the properties property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Properties }
+ *
+ */
+ public void setProperties(Properties value) {
+ this.properties = value;
+ }
+
+ /**
+ * Gets the value of the tileset property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the tileset property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getTileset().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Tileset }
+ *
+ *
+ */
+ public List<Tileset> getTileset() {
+ if (tileset == null) {
+ tileset = new ArrayList<Tileset>();
+ }
+ return this.tileset;
+ }
+
+ /**
+ * Gets the value of the layerOrObjectgroup property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the layerOrObjectgroup property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getLayerOrObjectgroup().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Layer }
+ * {@link Objectgroup }
+ *
+ *
+ */
+ public List<java.lang.Object> getLayerOrObjectgroup() {
+ if (layerOrObjectgroup == null) {
+ layerOrObjectgroup = new ArrayList<java.lang.Object>();
+ }
+ return this.layerOrObjectgroup;
+ }
+
+}
--- /dev/null
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2013.02.27 at 01:07:39 PM CST
+//
+
+
+package duskz.io.tiled;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+
+/**
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "properties",
+ "image"
+})
+@XmlRootElement(name = "object")
+public class Object {
+
+ @XmlAttribute(name = "name", required = true)
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String name;
+ @XmlAttribute(name = "type", required = true)
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String type;
+ @XmlAttribute(name = "x", required = true)
+ protected int x;
+ @XmlAttribute(name = "y", required = true)
+ protected int y;
+ @XmlAttribute(name = "width")
+ protected int width;
+ @XmlAttribute(name = "height")
+ protected int height;
+ protected Properties properties;
+ protected Image image;
+
+ /**
+ * Gets the value of the name property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setName(String value) {
+ this.name = value;
+ }
+
+ /**
+ * Gets the value of the type property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Sets the value of the type property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setType(String value) {
+ this.type = value;
+ }
+
+ /**
+ * Gets the value of the x property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getX() {
+ return x;
+ }
+
+ /**
+ * Sets the value of the x property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setX(int value) {
+ this.x = value;
+ }
+
+ /**
+ * Gets the value of the y property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getY() {
+ return y;
+ }
+
+ /**
+ * Sets the value of the y property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setY(int value) {
+ this.y = value;
+ }
+
+ /**
+ * Gets the value of the width property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Sets the value of the width property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setWidth(int value) {
+ this.width = value;
+ }
+
+ /**
+ * Gets the value of the height property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Sets the value of the height property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setHeight(int value) {
+ this.height = value;
+ }
+
+ /**
+ * Gets the value of the properties property.
+ *
+ * @return
+ * possible object is
+ * {@link Properties }
+ *
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Sets the value of the properties property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Properties }
+ *
+ */
+ public void setProperties(Properties value) {
+ this.properties = value;
+ }
+
+ /**
+ * Gets the value of the image property.
+ *
+ * @return
+ * possible object is
+ * {@link Image }
+ *
+ */
+ public Image getImage() {
+ return image;
+ }
+
+ /**
+ * Sets the value of the image property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Image }
+ *
+ */
+ public void setImage(Image value) {
+ this.image = value;
+ }
+
+}
--- /dev/null
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2013.02.27 at 01:07:39 PM CST
+//
+
+
+package duskz.io.tiled;
+
+import javax.xml.bind.annotation.XmlRegistry;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the generated package.
+ * <p>An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: generated
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link Tileset }
+ *
+ */
+ public Tileset createTileset() {
+ return new Tileset();
+ }
+
+ /**
+ * Create an instance of {@link Image }
+ *
+ */
+ public Image createImage() {
+ return new Image();
+ }
+
+ /**
+ * Create an instance of {@link Tile }
+ *
+ */
+ public Tile createTile() {
+ return new Tile();
+ }
+
+ /**
+ * Create an instance of {@link Properties }
+ *
+ */
+ public Properties createProperties() {
+ return new Properties();
+ }
+
+ /**
+ * Create an instance of {@link Objectgroup }
+ *
+ */
+ public Objectgroup createObjectgroup() {
+ return new Objectgroup();
+ }
+
+ /**
+ * Create an instance of {@link Object }
+ *
+ */
+ public Object createObject() {
+ return new Object();
+ }
+
+ /**
+ * Create an instance of {@link Data }
+ *
+ */
+ public Data createData() {
+ return new Data();
+ }
+
+ /**
+ * Create an instance of {@link Map }
+ *
+ */
+ public Map createMap() {
+ return new Map();
+ }
+
+ /**
+ * Create an instance of {@link Layer }
+ *
+ */
+ public Layer createLayer() {
+ return new Layer();
+ }
+
+ /**
+ * Create an instance of {@link Property }
+ *
+ */
+ public Property createProperty() {
+ return new Property();
+ }
+
+}
--- /dev/null
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2013.02.27 at 01:07:39 PM CST
+//
+
+
+package duskz.io.tiled;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+
+/**
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "object"
+})
+@XmlRootElement(name = "objectgroup")
+public class Objectgroup {
+
+ @XmlAttribute(name = "name", required = true)
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String name;
+ @XmlAttribute(name = "width")
+ protected int width;
+ @XmlAttribute(name = "height")
+ protected int height;
+ @XmlAttribute(name = "x")
+ protected int x;
+ @XmlAttribute(name = "y")
+ protected int y;
+ protected List<Object> object;
+
+ /**
+ * Gets the value of the name property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setName(String value) {
+ this.name = value;
+ }
+
+ /**
+ * Gets the value of the width property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Sets the value of the width property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setWidth(int value) {
+ this.width = value;
+ }
+
+ /**
+ * Gets the value of the height property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Sets the value of the height property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setHeight(int value) {
+ this.height = value;
+ }
+
+ /**
+ * Gets the value of the x property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getX() {
+ return x;
+ }
+
+ /**
+ * Sets the value of the x property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setX(int value) {
+ this.x = value;
+ }
+
+ /**
+ * Gets the value of the y property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getY() {
+ return y;
+ }
+
+ /**
+ * Sets the value of the y property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setY(int value) {
+ this.y = value;
+ }
+
+ /**
+ * Gets the value of the object property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the object property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getObject().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Object }
+ *
+ *
+ */
+ public List<Object> getObject() {
+ if (object == null) {
+ object = new ArrayList<Object>();
+ }
+ return this.object;
+ }
+
+}
--- /dev/null
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2013.02.27 at 01:07:39 PM CST
+//
+
+
+package duskz.io.tiled;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "property"
+})
+@XmlRootElement(name = "properties")
+public class Properties {
+
+ protected List<Property> property;
+
+ /**
+ * Gets the value of the property property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the property property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getProperty().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Property }
+ *
+ *
+ */
+ public List<Property> getProperty() {
+ if (property == null) {
+ property = new ArrayList<Property>();
+ }
+ return this.property;
+ }
+
+}
--- /dev/null
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2013.02.27 at 01:07:39 PM CST
+//
+
+
+package duskz.io.tiled;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+
+/**
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "")
+@XmlRootElement(name = "property")
+public class Property {
+
+ @XmlAttribute(name = "name", required = true)
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String name;
+ @XmlAttribute(name = "value", required = true)
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String value;
+
+ /**
+ * Gets the value of the name property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setName(String value) {
+ this.name = value;
+ }
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+}
--- /dev/null
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2013.02.27 at 01:07:39 PM CST
+//
+
+
+package duskz.io.tiled;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+
+/**
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "properties",
+ "image"
+})
+@XmlRootElement(name = "tile")
+public class Tile {
+
+ @XmlAttribute(name = "id")
+ protected int id;
+ @XmlAttribute(name = "gid")
+ protected String gid;
+ protected Properties properties;
+ protected Image image;
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setId(int value) {
+ this.id = value;
+ }
+
+ /**
+ * Gets the value of the gid property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getGid() {
+ return gid;
+ }
+
+ /**
+ * Sets the value of the gid property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setGid(String value) {
+ this.gid = value;
+ }
+
+ /**
+ * Gets the value of the properties property.
+ *
+ * @return
+ * possible object is
+ * {@link Properties }
+ *
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Sets the value of the properties property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Properties }
+ *
+ */
+ public void setProperties(Properties value) {
+ this.properties = value;
+ }
+
+ /**
+ * Gets the value of the image property.
+ *
+ * @return
+ * possible object is
+ * {@link Image }
+ *
+ */
+ public Image getImage() {
+ return image;
+ }
+
+ /**
+ * Sets the value of the image property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Image }
+ *
+ */
+ public void setImage(Image value) {
+ this.image = value;
+ }
+
+}
--- /dev/null
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2013.02.27 at 01:07:39 PM CST
+//
+
+
+package duskz.io.tiled;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+
+/**
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "image",
+ "tile"
+})
+@XmlRootElement(name = "tileset")
+public class Tileset {
+
+ @XmlAttribute(name = "name")
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String name;
+ @XmlAttribute(name = "firstgid", required = true)
+ protected int firstgid;
+ @XmlAttribute(name = "source")
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String source;
+ @XmlAttribute(name = "tilewidth")
+ protected int tilewidth;
+ @XmlAttribute(name = "tileheight")
+ protected int tileheight;
+ @XmlAttribute(name = "spacing")
+ protected int spacing;
+ @XmlAttribute(name = "margin")
+ @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
+ protected String margin;
+ protected List<Image> image;
+ protected List<Tile> tile;
+
+ /**
+ * Gets the value of the name property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setName(String value) {
+ this.name = value;
+ }
+
+ /**
+ * Gets the value of the firstgid property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getFirstgid() {
+ return firstgid;
+ }
+
+ /**
+ * Sets the value of the firstgid property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setFirstgid(int value) {
+ this.firstgid = value;
+ }
+
+ /**
+ * Gets the value of the source property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getSource() {
+ return source;
+ }
+
+ /**
+ * Sets the value of the source property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setSource(String value) {
+ this.source = value;
+ }
+
+ /**
+ * Gets the value of the tilewidth property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getTilewidth() {
+ return tilewidth;
+ }
+
+ /**
+ * Sets the value of the tilewidth property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setTilewidth(int value) {
+ this.tilewidth = value;
+ }
+
+ /**
+ * Gets the value of the tileheight property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getTileheight() {
+ return tileheight;
+ }
+
+ /**
+ * Sets the value of the tileheight property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setTileheight(int value) {
+ this.tileheight = value;
+ }
+
+ /**
+ * Gets the value of the spacing property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public int getSpacing() {
+ return spacing;
+ }
+
+ /**
+ * Sets the value of the spacing property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setSpacing(int value) {
+ this.spacing = value;
+ }
+
+ /**
+ * Gets the value of the margin property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMargin() {
+ return margin;
+ }
+
+ /**
+ * Sets the value of the margin property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMargin(String value) {
+ this.margin = value;
+ }
+
+ /**
+ * Gets the value of the image property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the image property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getImage().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Image }
+ *
+ *
+ */
+ public List<Image> getImage() {
+ if (image == null) {
+ image = new ArrayList<Image>();
+ }
+ return this.image;
+ }
+
+ /**
+ * Gets the value of the tile property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the tile property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getTile().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Tile }
+ *
+ *
+ */
+ public List<Tile> getTile() {
+ if (tile == null) {
+ tile = new ArrayList<Tile>();
+ }
+ return this.tile;
+ }
+
+}
--- /dev/null
+/*
+ * Jus test code, public domain
+ */
+package duskz.proto;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.security.AccessControlContext;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.security.cert.Certificate;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import javax.script.SimpleScriptContext;
+
+/**
+ * This is just a place holder to test stuff in the ide
+ *
+ *
+ * for security test: java -Djava.security.manager -Djava.security.policy=dusk.policy -classpath dist/DuskCommon.jar au.dusk.Junk
+ *
+ * @author notzed
+ */
+public class Junk {
+
+ int MapColumns = 64;
+ int MapRows = 64;
+ int viewrange = 7;
+ int mapsize = 1 + (2 * viewrange);
+
+ public void chatMessage(String inMessage, int intLocX, int intLocY, String strFrom) {
+
+ System.out.printf("look at %d,%d\n", intLocX, intLocY);
+
+
+ int mx, y0, my;
+ mx = 0;
+ if (intLocX - viewrange < 0) {
+ mx = -1 * (intLocX - viewrange);
+ }
+ y0 = 0;
+ if (intLocY - viewrange < 0) {
+ y0 = -1 * (intLocY - viewrange);
+ }
+ for (; mx < mapsize; mx++) {
+ if (intLocX + mx - viewrange < MapColumns) {
+ for (my = y0; my < mapsize; my++) {
+ if (intLocY + my - viewrange < MapRows) {
+ int x = intLocX + mx - viewrange;
+ int y = intLocY + my - viewrange;
+
+ System.out.printf("visit %d,%d\n", x, y);
+ }
+ }
+ }
+ }
+ }
+
+ public static class Thing {
+
+ FileOutputStream fos;
+
+ public Thing() {
+ try {
+ fos = new FileOutputStream("foo.txt");
+ } catch (FileNotFoundException ex) {
+ Logger.getLogger(Junk.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ public boolean isPet() {
+ return false;
+ }
+
+ public boolean hasCondition(String name) {
+ System.out.println("has trigger " + name);
+ return true;
+ }
+
+ public void removeCondition(String name) {
+ System.out.println("remove trigger " + name);
+ }
+
+ public void moveTo(int x, int y) {
+ System.out.println("move to " + x + "," + y);
+ }
+
+ public void chat(String what) {
+ try {
+ //fos = new FileOutputStream("foo.txt");
+ fos.write(what.getBytes());
+ //fos.close();
+ } catch (IOException ex) {
+ Logger.getLogger(Junk.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ }
+ static ScriptEngine engine;
+
+ public static void main(String[] args) throws ScriptException, InterruptedException {
+ //new Junk().chatMessage(null, 16, 16, null);
+ //new Junk().chatMessage(null, 2, 2, null);
+ // create a script engine manager
+ // evaluate JavaScript code from given file - specified by first argument
+
+
+ try (FileOutputStream fos = new FileOutputStream("not-hack-a")) {
+ fos.write(1);
+ System.out.println("wrote not-hack-a");
+ } catch (IOException x) {
+ x.printStackTrace();
+ } catch (AccessControlException x) {
+ x.printStackTrace();
+ }
+
+
+ /*
+ SecurityManager sm = new SecurityManager() {
+ @Override
+ public void checkPermission(Permission perm, Object context) {
+ System.out.println("check perm ctx " + perm);
+ super.checkPermission(perm, context);
+
+ }
+
+ @Override
+ public void checkPermission(Permission perm) {
+ System.out.println("check perm " + perm);
+ super.checkPermission(perm);
+ }
+ };*/
+ //System.setSecurityManager(sm);
+
+
+ //System.setSecurityManager(new SecurityManager());
+
+ final Thing thing = new Thing();
+
+
+ Permissions perms = new Permissions();
+ //perms.add(new AllPermission());
+ //perms.add(new FilePermission("hack.txt", "read,write"));
+ // perms.add(new NetPermission("*"));
+ //perms.add(new RuntimePermission("accessDeclaredMembers"));
+ // Cast to Certificate[] required because of ambiguity:
+ ProtectionDomain domain = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), perms);
+ AccessControlContext ac = new AccessControlContext(
+ new ProtectionDomain[]{domain});
+
+ // This doesn't work: security permissions are lost in the next thing.
+ // bloody odd if you ask me
+ AccessController.doPrivileged(new PrivilegedAction<ScriptEngine>() {
+ @Override
+ public ScriptEngine run() {
+ ScriptEngineManager factory = new ScriptEngineManager();
+ engine = factory.getEngineByName("JavaScript");
+ return null;
+ }
+ });
+
+
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ ScriptEngineManager factory = new ScriptEngineManager();
+ engine = factory.getEngineByName("JavaScript");
+
+ ScriptContext ctx = new SimpleScriptContext();
+ ctx.getBindings(ScriptContext.ENGINE_SCOPE);
+
+ System.out.println("threaded = " + engine.getFactory().getParameter("THREADING"));
+
+ engine.put("trigger", thing);
+
+ Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ String s = "var out = new java.io.FileOutputStream('hack-thread.txt');"
+ + " out.write(65);"
+ + "out.close();"
+ + " println('write hack.txt');";
+ engine.eval(s);
+ } catch (ScriptException ex) {
+ ex.printStackTrace(System.out);
+ } catch (AccessControlException x) {
+ x.printStackTrace(System.out);
+ }
+ }
+ };
+ Thread t = new Thread(r);
+ t.start();
+
+ try {
+ engine.eval("println(\"hello world\");");
+ engine.eval("trigger.chat('this is a chat message from sandbox?');");
+ } catch (ScriptException ex) {
+ ex.printStackTrace(System.out);
+ } catch (AccessControlException x) {
+ x.printStackTrace(System.out);
+ }
+ try {
+ String s = "if (!trigger.isPet() &&"
+ + "trigger.hasCondition(\"walk\")) {"
+ + " trigger.removeCondition(\"walk\");"
+ + "trigger.moveTo(177,195);"
+ + "}";
+
+ engine.eval(s);
+ } catch (ScriptException ex) {
+ ex.printStackTrace(System.out);
+ } catch (AccessControlException x) {
+ x.printStackTrace(System.out);
+ }
+ try {
+ String s = "var out = java.lang.System.out;"
+ + " out.println('system out');";
+ engine.eval(s);
+ } catch (ScriptException ex) {
+ ex.printStackTrace(System.out);
+ } catch (AccessControlException x) {
+ x.printStackTrace(System.out);
+ }
+ try {
+ String s = "var out = new java.io.FileOutputStream('hack.txt');"
+ + " out.write(65);"
+ + "out.close();"
+ + " println('write hack.txt');";
+ engine.eval(s);
+ } catch (ScriptException ex) {
+ ex.printStackTrace(System.out);
+ } catch (AccessControlException x) {
+ x.printStackTrace(System.out);
+ }
+
+ try {
+ String s = "var out = new java.net.Socket('localhost', 7475);;"
+ + " println(out);";
+ engine.eval(s);
+ } catch (ScriptException ex) {
+ ex.printStackTrace(System.out);
+ } catch (AccessControlException x) {
+ x.printStackTrace(System.out);
+ }
+ try {
+ String s = "var out = new java.lang.Thread();"
+ + " println(out);";
+ engine.eval(s);
+ } catch (ScriptException ex) {
+ ex.printStackTrace(System.out);
+ } catch (AccessControlException x) {
+ x.printStackTrace(System.out);
+ }
+ return null;
+ }
+ }, ac);
+
+ try (FileOutputStream fos = new FileOutputStream("not-hack-b")) {
+ fos.write(1);
+ System.out.println("wrote not-hack-b");
+ } catch (IOException x) {
+ x.printStackTrace();
+ } catch (AccessControlException x) {
+ x.printStackTrace(System.out);
+ }
+
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - Pretty major cleanup and parameterisation of code.
+ */
+package duskz.server;
+
+import duskz.protocol.MessageType;
+import duskz.server.entity.Mob;
+import duskz.server.entity.LivingThing;
+import duskz.server.entity.Item;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+/**
+ * Battle represents a fight between two sides comprised of LivingThings.
+ *
+ * TODO: Remove the general chat stuff and use specific message types where appropriate
+ *
+ * @author Tom Weingarten
+ */
+public class Battle {
+
+ private ArrayList<LivingThing> vctSide1 = new ArrayList<>(),
+ vctSide2 = new ArrayList<>();
+ DuskEngine engGame;
+ boolean blnRunning = true,
+ blnPlayerSide1 = false,
+ blnPlayerSide2 = false;
+ private HashMap<Long, LinkedList<String>> commands = new HashMap<>();
+
+ Battle(LivingThing inpla1, LivingThing inpla2, DuskEngine inengGame) {
+ LivingThing thnFront1,
+ thnFront2;
+ try {
+ engGame = inengGame;
+ thnFront2 = inpla2;
+ while (thnFront2 != null) {
+ blnPlayerSide2 = addToBattle(2, vctSide2, vctSide1, thnFront2, blnPlayerSide2, blnPlayerSide1);
+ //addToBattle(thnFront2, 2);
+ thnFront2 = thnFront2.getFollowing();
+ }
+ thnFront2 = inpla2.getMaster();
+ while (thnFront2 != null) {
+ blnPlayerSide2 = addToBattle(2, vctSide2, vctSide1, thnFront2, blnPlayerSide2, blnPlayerSide1);
+ //addToBattle(thnFront2, 2);
+ thnFront2 = thnFront2.getMaster();
+ }
+ thnFront2 = inpla2;
+ thnFront1 = inpla1;
+ while (thnFront1 != null) {
+ //addToBattle(thnFront1, 1);
+ blnPlayerSide1 = addToBattle(1, vctSide1, vctSide2, thnFront1, blnPlayerSide1, blnPlayerSide2);
+ thnFront1 = thnFront1.getFollowing();
+ }
+ thnFront1 = inpla1.getMaster();
+ while (thnFront1 != null) {
+ blnPlayerSide1 = addToBattle(1, vctSide1, vctSide2, thnFront1, blnPlayerSide1, blnPlayerSide2);
+ //addToBattle(thnFront1, 1);
+ thnFront1 = thnFront1.getMaster();
+ }
+ thnFront1 = inpla1;
+ engGame.chatMessage("-" + inpla1.name + " has attacked " + inpla2.name, inpla1.x, inpla1.y, "default");
+ if (inpla1.popup) {
+ inpla1.send(MessageType.StartBattle, inpla2.name + "\n");
+ }
+ if (inpla2.popup) {
+ inpla2.send(MessageType.StartBattle, inpla1.name + "\n");
+ }
+ } catch (Exception e) {
+ blnRunning = false;
+ engGame.log.printError("Battle()", e);
+ }
+ }
+
+ public static LivingThing getEnemy(LivingThing lt) {
+ if (lt.battleSide == 1) {
+ return (LivingThing) lt.battle.vctSide2.get(0);
+ } else if (lt.battleSide == 2) {
+ return (LivingThing) lt.battle.vctSide1.get(0);
+ } else {
+ return null;
+ }
+ }
+
+ public void addToBattle(LivingThing lt, int side) {
+ if (side == 1) {
+ blnPlayerSide1 = addToBattle(1, vctSide1, vctSide2, lt, blnPlayerSide1, blnPlayerSide2);
+ } else {
+ blnPlayerSide2 = addToBattle(2, vctSide2, vctSide1, lt, blnPlayerSide2, blnPlayerSide1);
+ }
+ }
+
+ boolean addToBattle(int sideid, ArrayList<LivingThing> side, ArrayList<LivingThing> opponents, LivingThing thnAdded, boolean playerSide, boolean playerOpponent) {
+ if (thnAdded.isPlayer()) {
+ if (playerOpponent) {
+ if (thnAdded.clan.equals("none")) {
+ thnAdded.chatMessage("Players who are not in clans cannot fight other players.");
+ thnAdded.removeFromGroup();
+ return playerSide;
+ }
+ LivingThing thnStore = side.get(0);
+ if (thnStore.clan.equals("none")) {
+ thnAdded.chatMessage("Players who are not in clans cannot fight other players.");
+ thnAdded.removeFromGroup();
+ return playerSide;
+ }
+ }
+ playerSide = true;
+ if (engGame.blnMusic) {
+ thnAdded.playMusic(1);
+ }
+ }
+ chatMessage("\t" + thnAdded.name + " has joined the battle.");
+ side.add(thnAdded);
+ thnAdded.enterBattle(this, sideid);
+
+ for (LivingThing lt : side) {
+ if (lt.highlight) {
+ lt.updateFlag(thnAdded.ID, 1);
+ }
+ if (thnAdded.highlight) {
+ thnAdded.updateFlag(lt.ID, 1);
+ }
+ }
+ for (LivingThing lt : opponents) {
+ if (lt.highlight) {
+ lt.updateFlag(thnAdded.ID, 2);
+ }
+ if (thnAdded.highlight) {
+ thnAdded.updateFlag(lt.ID, 2);
+ }
+ }
+ return playerSide;
+ }
+
+ String attack(LivingThing attackor, LivingThing attackee, int range, String s) {
+ // The farther away the target, the harder they are to hit.
+ // The more skilled the attecker is in ranged combat, the less range affects ability to hit.
+ // The farther away the target, the easier it is for them to dodge.
+ // The more skilled the attecker is in ranged combat, the harder it is for the target to dodge.
+ int r2 = 0;
+ if (range > 1) {
+// r2= thnAttacking.getSkill("ranged combat") - (int)((range * range - 1) * (double)(100/engGame.viewrange));
+ r2 = attackor.getSkill("ranged combat");
+ } else {
+ r2 = attackor.getSkill("close combat");
+ }
+ if (r2 < 0) {
+ s += attackor.name + " missed.";
+ hitMessage(attackee.getID(), 0, attackee.hp, attackee.maxhp, attackor.getID(), "Missed!");
+ } else if (dodge(attackor, attackee, r2)) {
+ s += attackee.name + " dodged " + attackor.name + "'s attack";
+ hitMessage(attackee.getID(), 0, attackee.hp, attackee.maxhp, attackor.getID(), "Dodged!");
+ } else {
+ if (engGame.battlesound != -1) {
+ engGame.playSound(engGame.battlesound, attackee.x, attackee.y);
+ }
+ int i = damRoll(attackor, attackee, range);
+ if (i < 0) {
+ i = 0;
+ }
+ s += attackor.name + " did " + i + " to " + attackee.name;
+ attackee.hp -= i;
+ attackor.damageDone += i;
+ attackor.weaponDam(i);
+ attackee.armorDam(i);
+
+ hitMessage(attackee.getID(), i, attackee.hp, attackee.maxhp, attackor.getID(), "Hit!");
+ }
+ return s;
+ }
+
+ /**
+ * Attack everything in side1 against side2
+ *
+ * @param list1
+ * @param list2
+ * @return true if the battle continues
+ */
+ boolean attackSide(ArrayList<LivingThing> list1, ArrayList<LivingThing> list2) {
+ int range;
+ LivingThing target;
+ String msg;
+
+ checkCommands(list1, list2);
+ if (list1.isEmpty()) {
+ endBattle();
+ return false;
+ }
+
+ for (LivingThing attackor : list1) {
+ msg = "";
+ if (attackor.isMob()) {
+ Mob mobStore = (Mob) attackor;
+ mobStore.onBattle(engGame);
+ }
+
+ range = Integer.MAX_VALUE;
+ target = null;
+ attackor.isMoveable = true;
+ for (LivingThing t : list2) {
+ int distance = attackor.distance(t);
+ if (distance < range) {
+ range = distance;
+ target = t;
+ }
+ /*
+ They are allowed to move until they are at a range of 1 or less with any target
+ */
+ t.isMoveable = true;
+ if (attackor.adjacent(t)) {
+ attackor.isMoveable = false;
+ t.isMoveable = false;
+ }
+ }
+
+ /*
+ End the battle if the closest target is off of the screen.
+ */
+ if (range > engGame.viewrange) {
+ endBattle();
+ return false;
+ }
+ if (range > attackor.getRangeWithBonus()) {
+ msg = attackor.name + " is out of range.\n";
+ if (attackor.isMob() && !attackor.hasPendingMoves()) // if mob, try to go to the enemy to fight them
+ {
+ attackor.goTo(target.x, target.y, false);
+ }
+ } else {
+ if (attackor.isMob())
+ attackor.clearMoveQueue();
+ msg = attack(attackor, target, range, msg);
+ if (((Math.random() * 100) + 1) < attackor.getSkill("double attack")) {
+ msg += ",";
+ msg = attack(attackor, target, range, msg);
+ }
+ if (((Math.random() * 100) + 1) < attackor.getSkill("triple attack")) {
+ msg += ",";
+ msg = attack(attackor, target, range, msg);
+ }
+ if (((Math.random() * 100) + 1) < attackor.getSkill("quadruple attack")) {
+ msg += ",";
+ msg = attack(attackor, target, range, msg);
+ }
+ msg += ".";
+ }
+ chatMessage("\t" + msg);
+ }
+ return true;
+ }
+
+ int damRoll(LivingThing attacker, LivingThing thnAttacked, int range) {
+ int attackerTotal = attacker.stre + attacker.strebon;
+ return (int) (((double) (attackerTotal) / 2) * (Math.random() + 0.5) * (attacker.getDamModWithBonus() / 100) - (thnAttacked.getArmorModWithBonus()));
+ }
+
+ boolean dodge(LivingThing attacker, LivingThing thnAttacked, int attackModifier) {
+ int attackedTotal = thnAttacked.dext + thnAttacked.dextbon;
+ if (attackedTotal > 100) {
+ attackedTotal = 100;
+ }
+ int attackerTotal = attacker.dext + attacker.dextbon + attackModifier;
+ if (attackerTotal > 100) {
+ attackerTotal = 100 + attackModifier;
+ }
+ return ((Math.random() * 100) < ((thnAttacked.getSkill("Dodge") * .75) + (.25 * (attackedTotal - attackerTotal))));
+ }
+
+ void endBattle(ArrayList<LivingThing> list) {
+ for (LivingThing lt : list) {
+ lt.clearFlags();
+ lt.battle = null;
+ lt.battleSide = 0;
+ lt.isMoveable = true;
+ lt.updateInfo();
+ lt.updateStats();
+ lt.updateActions();
+ lt.playMusic(0);
+ }
+ }
+
+ void endBattle() {
+ blnRunning = false;
+ chatMessage("\tYou have won the battle.");
+ endBattle(vctSide1);
+ endBattle(vctSide2);
+ }
+
+ void flee(LivingThing thnStore, ArrayList<LivingThing> list, ArrayList<LivingThing> opponents) {
+ thnStore.clearFlags();
+
+ updateFlagsSelf(vctSide1, 0);
+ updateFlagsSelf(vctSide2, 0);
+
+ if (thnStore.getFollowing() != null && thnStore.getFollowing().isPet()) {
+ if (thnStore.getMaster() != null) {
+ thnStore.getMaster().setFollowing(thnStore.getFollowing().getFollowing());
+ }
+ if (thnStore.getFollowing().getFollowing() != null) {
+ thnStore.getFollowing().getFollowing().setMaster(thnStore.getMaster());
+ }
+ } else {
+ if (thnStore.getMaster() != null) {
+ thnStore.getMaster().setFollowing(thnStore.getFollowing());
+ }
+ if (thnStore.getFollowing() != null) {
+ thnStore.getFollowing().setMaster(thnStore.getMaster());
+ }
+ }
+ list.remove(thnStore);
+ if (thnStore.popup) {
+ thnStore.send("" + (char) 33 + "You have fled from battle\n");
+ } else {
+ thnStore.chatMessage("You have fled from battle");
+ }
+ splitMoney(thnStore, (int) (thnStore.cash * engGame.gpfleemod), opponents);
+ splitExp(thnStore, (int) (thnStore.exp * engGame.expfleemod), opponents);
+ thnStore.leaveBattle();
+ thnStore.updateInfo();
+ thnStore.updateStats();
+ thnStore.updateActions();
+ thnStore.playMusic(0);
+ if (thnStore.getFollowing() != null && thnStore.getFollowing().isPet()) {
+ list.remove(thnStore.getFollowing());
+ updateFlags(vctSide1, thnStore.getFollowing().ID, 0);
+ updateFlags(vctSide2, thnStore.getFollowing().ID, 0);
+ thnStore.getFollowing().leaveBattle();
+ }
+ if (vctSide2.size() == 0 || vctSide1.size() == 0) {
+ endBattle();
+ return;
+ }
+ }
+
+ void splitMoney(LivingThing thnStore, int money, ArrayList<LivingThing> opponents) {
+ if (money == 0) {
+ return;
+ }
+ if (thnStore.popup) {
+ thnStore.send("" + (char) 33 + "You have lost " + money + " gp.\n");
+ } else {
+ thnStore.chatMessage("You have lost " + money + " gp.");
+ }
+ thnStore.cash -= money;
+ int i,
+ i2 = 0;
+ LivingThing thnStore2;
+ try {
+ /*
+ for (i=0;i<vctStore.size();i++)
+ {
+ thnStore2 = (LivingThing)vctStore.elementAt(i);
+ // added "|| thnStore2.isPet()"
+ if (thnStore2.isPlayer() || thnStore2.isPet())
+ {
+ i2++;
+ }
+ }
+ i2 = money/i2;
+ */
+ i2 = money / opponents.size();
+ for (i = 0; i < opponents.size(); i++) {
+ thnStore2 = (LivingThing) opponents.get(i);
+ thnStore2.cash += i2;
+ if (thnStore2.isPlayer() && i2 != 0) {
+ thnStore2.chatMessage("\tYou get " + i2 + " gp.");
+ }
+ }
+ } catch (Exception e) {
+ engGame.log.printError("splitMoney()", e);
+ }
+ }
+
+ void splitExp(LivingThing thnFront, int exp, ArrayList<LivingThing> opponents) {
+ if (thnFront.popup) {
+ thnFront.send("" + (char) 33 + "You have lost " + exp + " exp.\n");
+ } else {
+ thnFront.chatMessage("You have lost " + exp + " exp.");
+ }
+ thnFront.exp -= exp;
+ double tp,
+ sidepoints = 0;
+ //LivingThing thnFront;
+ //if (thnFront.bytSide == 1) {
+ // thnFront = vctSide1.get(0);
+ //} else {
+ // thnFront = vctSide2.get(0);
+ //}
+ int i,
+ i2 = 0;
+ LivingThing thnStore2;
+
+ tp = thnFront.getTotalPoints();
+ thnFront.damageDone = 0;
+ for (i = 0; i < opponents.size(); i++) {
+ thnStore2 = (LivingThing) opponents.get(i);
+// added "|| thnStore2.isPet()"
+// and changed "thnStore.getTotalPoints()" to "thnStore2.getTotalPoints()"
+// if (thnStore2.isPlayer() || thnStore2.isPet())
+// {
+ sidepoints += thnStore2.getTotalPoints();
+// }
+ }
+ try {
+ for (i = 0; i < opponents.size(); i++) {
+ i2 = 0;
+ thnStore2 = (LivingThing) opponents.get(i);
+ if (!thnStore2.isMob()) {
+ if (thnStore2.damageDone > thnFront.maxhp) {
+ thnStore2.damageDone = thnFront.maxhp;
+ }
+ i2 = (int) (engGame.expgainmod
+ * (((tp / sidepoints)
+ + (2 * (thnStore2.damageDone / (double) thnFront.maxhp) * (tp / (double) thnStore2.getTotalPoints()))) / 3));
+ thnStore2.chatMessage("You get " + i2 + " exp.");
+ thnStore2.exp += i2;
+ }
+ thnStore2.damageDone = 0;
+ }
+ } catch (Exception e) {
+ engGame.log.printError("splitExp()", e);
+ }
+ }
+
+ void chatMessage(ArrayList<LivingThing> side1, ArrayList<LivingThing> side2, String strStore) {
+ LivingThing thnStore = null;
+ String strStore2 = null;
+ if (!side2.isEmpty()) {
+ thnStore = (LivingThing) side2.get(0);
+ strStore2 = thnStore.name + " has " + thnStore.getCharacterPoints() + "cp and " + thnStore.hp + "/" + thnStore.maxhp + "hp.";
+ }
+ for (int i = 0; i < side1.size(); i++) {
+ thnStore = (LivingThing) side1.get(i);
+ if (thnStore.isPlayer()) {
+ if (thnStore.popup) {
+ if (strStore2 != null) {
+ thnStore.send(MessageType.UpdateBattle, strStore2 + "\n");
+ thnStore.send(MessageType.LogBattle, strStore + "\n");
+ }
+ } else {
+ thnStore.chatMessage(strStore);
+ }
+ } else if (thnStore.isPet()) {
+ if (thnStore.getMaster().battle != thnStore.battle) {
+ if (thnStore.getMaster().popup) {
+ if (strStore2 != null) {
+ thnStore.getMaster().send(MessageType.UpdateBattle, "From " + thnStore.name + ": " + strStore2 + "\n");
+ thnStore.getMaster().send(MessageType.LogBattle, "From " + thnStore.name + ": " + strStore + "\n");
+ }
+ } else {
+ thnStore.chatMessage(strStore);
+ }
+ }
+ }
+ }
+ }
+
+ void chatMessage(String strStore) {
+ chatMessage(vctSide1, vctSide2, strStore);
+ chatMessage(vctSide2, vctSide1, strStore);
+ }
+
+ void battleMessage(ArrayList<LivingThing> side1, MessageType type, String msg) {
+ for (LivingThing thnStore : side1) {
+ if (thnStore.isPlayer()) {
+ thnStore.send(type, msg);
+ } else if (thnStore.isPet()) {
+ if (thnStore.getMaster().battle != thnStore.battle) {
+ thnStore.send(type, msg);
+ }
+ }
+ }
+ }
+
+ /**
+ * New battle interface with more detailed messages
+ *
+ * @param type
+ * @param msg
+ */
+ void battleMessage(MessageType type, String msg) {
+ battleMessage(vctSide1, type, msg);
+ battleMessage(vctSide2, type, msg);
+ }
+
+ void hitMessage(long targetid, int delta, int targethp, int targettotalhp, long fromid, String what) {
+ battleMessage(MessageType.HitEntity,
+ String.format("%d\n%d\n%d\n%d\n%d\n%s\n.\n", targetid, delta, targethp, targettotalhp, fromid, what));
+ }
+
+ /**
+ * Add a command to a current battle
+ *
+ * @param lt
+ * @param cmd
+ */
+ public void addCommand(LivingThing lt, String cmd) {
+ synchronized (commands) {
+ LinkedList<String> clist = commands.get(lt.ID);
+ if (clist == null) {
+ clist = new LinkedList<>();
+ commands.put(lt.ID, clist);
+ }
+ clist.add(cmd);
+ }
+ }
+
+ /**
+ * Add an expidited command to the current battle. i.e. flee
+ *
+ * @param lt
+ * @param cmd
+ */
+ public void addFirstCommand(LivingThing lt, String cmd) {
+ synchronized (commands) {
+ LinkedList<String> clist = commands.get(lt.ID);
+ if (clist == null) {
+ clist = new LinkedList<>();
+ commands.put(lt.ID, clist);
+ }
+ clist.addFirst(cmd);
+ }
+ }
+
+ void checkCommands(ArrayList<LivingThing> list, ArrayList<LivingThing> opponents) {
+ for (LivingThing lt : list) {
+ String cmd = null;
+ synchronized (commands) {
+ LinkedList<String> clist = commands.get(lt.ID);
+ if (clist != null) {
+ cmd = clist.removeFirst();
+ }
+ }
+ if (cmd != null) {
+ if (cmd.equalsIgnoreCase("flee")) {
+ flee(lt, list, opponents);
+ } else if (cmd.startsWith("cast ")) {
+ cmd = cmd.substring(5, cmd.length());
+ lt.castSpell(cmd);
+ } else if (cmd.startsWith("use ")) {
+ cmd = cmd.substring(4, cmd.length());
+ lt.useItem(cmd, -1);
+ } else if (cmd.startsWith("eat ")) {
+ cmd = cmd.substring(4, cmd.length());
+ lt.useItem(cmd, Item.FOOD);
+ } else if (cmd.startsWith("drink ")) {
+ cmd = cmd.substring(6, cmd.length());
+ lt.useItem(cmd, Item.DRINK);
+ }
+ }
+ }
+ }
+
+ void update(ArrayList<LivingThing> list) {
+ for (LivingThing lt : list) {
+ if (lt.isPlayer()) {
+ lt.updateInfo();
+ lt.updateStats();
+ }
+ }
+ }
+
+ void update() {
+ update(vctSide1);
+ update(vctSide2);
+ }
+
+ void updateFlags(ArrayList<LivingThing> list, long ID, int flag) {
+ for (LivingThing lt : list) {
+ lt.updateFlag(ID, flag);
+ }
+ }
+
+ void updateFlagsSelf(ArrayList<LivingThing> list, int flag) {
+ for (LivingThing lt : list) {
+ lt.updateFlag(lt.ID, flag);
+ }
+ }
+
+ void checkDeath(ArrayList<LivingThing> vctSide1, ArrayList<LivingThing> vctSide2) {
+ // FIXME: verify this works. this protects the second call
+ if (vctSide1.isEmpty() || vctSide2.isEmpty())
+ return;
+
+ LivingThing thnFront1 = vctSide1.get(0);
+ LivingThing thnFront2 = vctSide2.get(0);
+
+ if (thnFront2.hp < 1 || !thnFront2.isWorking) {
+ vctSide2.remove(0);
+
+ System.out.println(thnFront2 + " died\nRemaining in fight:");
+ for (LivingThing lt : vctSide2) {
+ System.out.println(" " + lt);
+ }
+
+ thnFront2.clearFlags();
+ updateFlags(vctSide1, thnFront2.ID, 0);
+ updateFlags(vctSide2, thnFront2.ID, 0);
+ if (thnFront2.isPlayer()) {
+ thnFront2.removeFromGroup();
+ chatMessage("\t" + thnFront2.name + " is killed.");
+ if (thnFront2.popup) {
+ thnFront2.send("" + (char) 33 + "\tYou have died.\n");
+ } else {
+ thnFront2.chatMessage("\tYou have died.");
+ }
+ splitMoney(thnFront2, (int) (thnFront2.cash * engGame.gplosemod), vctSide1);
+ splitExp(thnFront2, (int) (thnFront2.exp * engGame.explosemod), vctSide1);
+ thnFront2.leaveBattle();
+ thnFront2.updateInfo();
+ thnFront2.updateStats();
+ thnFront2.updateActions();
+ thnFront2.playMusic(0);
+ engGame.chatMessage(thnFront2.name + " has been killed by " + thnFront1.name, "default");
+ if (engGame.scrOnDeath != null && thnFront2.isWorking) {
+ engGame.scrOnDeath.varVariables.clearVariables();
+ engGame.scrOnDeath.varVariables.addVariable("trigger", thnFront2);
+ engGame.scrOnDeath.varVariables.addVariable("killer", thnFront1);
+ engGame.scrOnDeath.runScript();
+ }
+ if (thnFront2.getFollowing() != null && thnFront2.getFollowing().isPet()) {
+ vctSide2.remove(thnFront2.getFollowing());
+ updateFlags(vctSide1, thnFront2.getFollowing().ID, 0);
+ updateFlags(vctSide2, thnFront2.getFollowing().ID, 0);
+ thnFront2.getFollowing().leaveBattle();
+ thnFront2.getFollowing().damageDone = 0;
+ thnFront2.getFollowing().changeLocBypass(thnFront2.x, thnFront2.y);
+ }
+ } else if (thnFront2.isMob()) {
+ Mob mob = (Mob) thnFront2;
+ chatMessage("\t" + thnFront2.name + " is killed.");
+ splitMoney(thnFront2, (int) (thnFront2.cash), vctSide1);
+ splitExp(thnFront2, 0, vctSide1);
+ /**
+ * FIXME: Mobs are not fully removed from the game when they die.
+ * This seems very questionable, shouldn't they just be changed
+ * to "dead"?
+ */
+ mob.leaveBattle();
+ // if (mob.blnOneUse) {
+ // engGame.removeDuskObject(mob);
+ // } else {
+ // //engGame.removeDuskObject(mob);
+ // // Marks mob as "dead"
+ // mob.leaveBattle();
+ // }
+ for (LivingThing lt : vctSide1) {
+ if (!lt.isPet()) {
+ try {
+ mob.fctFaction.killedBy(mob, lt);
+ } catch (Exception e) {
+ engGame.log.printError("Battle.run():While updating faction for mob " + mob.name, e);
+ }
+ }
+ }
+ if (thnFront1.isPlayer()) {
+ Item itmStore;
+ for (GiveItem gitStore : mob.vctGiveItems) {
+ if (Math.random() < gitStore.dblProbability) {
+ itmStore = engGame.getItem(gitStore.strItemName);
+ if (itmStore != null) {
+ // FIXME: giveItem() on livingthing?
+ thnFront1.chatMessage("You got a " + gitStore.strItemName + ".");
+ thnFront1.itemList.addElement(itmStore);
+ itmStore.onGetItem(engGame, thnFront1);
+ thnFront1.updateItems();
+ }
+ }
+ }
+ }
+ } else if (thnFront2.isPet()) {
+ chatMessage("\t" + thnFront2.name + " is wounded.");
+ thnFront2.chatMessage("\tYou have been wounded.");
+ splitMoney(thnFront2, (int) (thnFront2.cash * engGame.gplosemod), vctSide1);
+ splitExp(thnFront2, (int) (thnFront2.exp * engGame.explosemod), vctSide1);
+ thnFront2.leaveBattle();
+ }
+ //if (!vctSide2.isEmpty()) {
+ // thnFront2 = vctSide2.get(0);
+ //}
+ }
+ }
+
+ public void run() {
+ if (!attackSide(vctSide1, vctSide2)) {
+ return;
+ }
+ if (!attackSide(vctSide2, vctSide1)) {
+ return;
+ }
+
+ checkDeath(vctSide1, vctSide2);
+ checkDeath(vctSide2, vctSide1);
+
+ if (vctSide2.isEmpty() || vctSide1.isEmpty()) {
+ endBattle();
+ return;
+ }
+ update();
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - modernised java
+ */
+package duskz.server;
+
+import duskz.server.entity.Mob;
+import duskz.server.entity.Merchant;
+import duskz.server.entity.Sign;
+import duskz.server.entity.Item;
+import duskz.server.entity.Prop;
+import duskz.server.entity.DuskObject;
+import duskz.server.entity.Equipment;
+import duskz.server.entity.PlayerMerchant;
+import duskz.server.entity.LivingThing;
+import java.io.*;
+import java.util.LinkedList;
+import java.util.StringTokenizer;
+
+public class Commands {
+
+ public static String parseCommand(LivingThing lt, DuskEngine game, String cmdline) throws Exception {
+ if (cmdline == null) {
+ return null;
+ }
+ if (lt == null) {
+ return null;
+ }
+ if (game == null) {
+ return null;
+ }
+
+ String cmd = null;
+ String args = null;
+
+ int intIndex = cmdline.indexOf(" ");
+ if (intIndex == -1) {
+ cmd = cmdline.toLowerCase();
+ } else {
+ cmd = cmdline.substring(0, intIndex).toLowerCase();
+ args = cmdline.substring(intIndex + 1).trim();
+ }
+
+ if (cmd.length() < 1) {
+ return "huh?";
+ }
+
+ lt.isAlwaysCommands = true;
+ boolean blnFoundScriptedCommand = false;
+ /*
+ ** Don't try to find a scripted command if they are doing a tell
+ */
+ if (cmd.substring(0, 1) != "/") {
+ try {
+ Script script = new Script("commands/" + cmd, game, false);
+ script.varVariables.addVariable("trigger", lt);
+ if (args != null) {
+ script.runScript(args);
+ } else {
+ script.runScript();
+ }
+ script.close();
+ blnFoundScriptedCommand = true;
+ } catch (Exception e) {
+ blnFoundScriptedCommand = false;
+ }
+ if (!lt.isAlwaysCommands) {
+ return null;
+ }
+ }
+ if (lt.privs > 2) {
+ if (cmdline.startsWith(">")) {
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ cmdline = cmdline.substring(1);
+ if (cmdline.equalsIgnoreCase("s")) {
+ if (game.blnSavingGame) {
+ return "Game already being saved, please wait.";
+ }
+ game.saveMap();
+ return "Game settings saved";
+ }
+
+ String strMapLog = "shortmap_redraw";
+ try (PrintStream psMap = new PrintStream(new FileOutputStream(strMapLog, true), true)) {
+ game.changeMap(lt.x, lt.y, Short.parseShort(cmdline));
+ psMap.println("changetile " + lt.x + " " + lt.y + " " + Short.parseShort(cmdline));
+ return null;
+ } catch (Exception e) {
+ game.log.printError("parseCommand():While " + lt.name + " tried to >" + cmdline, e);
+ return null;
+ }
+ }
+ if (cmdline.startsWith("<")) {
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ cmdline = cmdline.substring(1);
+ if (cmdline.equals("s")) {
+ if (game.blnSavingGame) {
+ return "Game already being saved, please wait.";
+ }
+ game.saveMap();
+ return "Game settings saved";
+ } else if (cmdline.equalsIgnoreCase("merchant")) {
+ if (game.overMerchant(lt.x, lt.y) != null) {
+ return "There's already a merchant there.";
+ }
+ if (game.overPlayerMerchant(lt.x, lt.y) != null) {
+ return "There's already a merchant there.";
+ }
+ Merchant mrcStore = new Merchant(game);
+ mrcStore.x = lt.x;
+ mrcStore.y = lt.y;
+ //game.vctMerchants.add(mrcStore);
+ //game.blnMerchantListChanged = true;
+ game.addDuskObject(mrcStore);
+ return null;
+ } else if (cmdline.toLowerCase().startsWith("prop ")) {
+ if (cmdline.length() == 5) {
+ return "Add what prop?";
+ }
+ cmdline = cmdline.substring(5);
+ Prop prpStore = game.getProp(cmdline);
+ if (prpStore != null) {
+ prpStore.x = lt.x;
+ prpStore.y = lt.y;
+ //game.vctProps.addElement(prpStore);
+ //game.blnPropListChanged = true;
+ game.addDuskObject(prpStore);
+ }
+ return null;
+ } else if (cmdline.startsWith("sign ")) {
+ if (cmdline.length() == 5) {
+ return "What should the sign say?";
+ }
+ Sign sgnStore = new Sign(game, "sign", cmdline.substring(5), lt.x, lt.y, game.getID());
+ //game.vctSigns.add(sgnStore);
+ //game.blnSignListChanged = true;
+ game.addDuskObject(sgnStore);
+ return null;
+ }
+ Item itmStore = game.getItem(cmdline);
+ if (itmStore != null) {
+ itmStore.x = lt.x;
+ itmStore.y = lt.y;
+ //game.vctItems.add(itmStore);
+ game.addDuskObject(itmStore);
+ return null;
+ }
+ try {
+ Mob mob = new Mob(cmdline, lt.x, lt.y, game);
+ // TODO: this previously didn't call addDuskObject - bug or intentional?
+ //game.vctMobs.addElement(mob);
+ //game.blnMobListChanged = true;
+ game.addDuskObject(mob);
+
+ mob.changeLocBypass(lt.x, lt.y);
+ } catch (Exception e) {
+ game.log.printError("parseCommand():While creating mob \"" + cmdline + "\"", e);
+ }
+ return null;
+ }
+ }
+
+ // Remap shortcuts
+ if (cmd.startsWith(";")) {
+ args = cmdline.substring(1).trim();
+ cmd = "gossip";
+ }
+ if (cmd.startsWith(":")) {
+ args = cmdline.substring(1).trim();
+ cmd = "clan";
+ }
+ if (cmd.startsWith("'")) {
+ args = cmdline.substring(1).trim();
+ cmd = "say";
+ }
+ if (cmd.startsWith(".")) {
+ args = cmdline.substring(1).trim();
+ cmd = "emote";
+ }
+ if (cmd.startsWith("/")) {
+ args = cmdline.substring(1).trim();
+ cmd = "tell";
+ }
+
+ switch (cmd) {
+ case "north":
+ case "n":
+ if (!lt.moveAfterClear("n")) {
+ return "You can't move while you're following someone.";
+ }
+ return null;
+ case "south":
+ case "s":
+ if (!lt.moveAfterClear("s")) {
+ return "You can't move while you're following someone.";
+ }
+ return null;
+ case "west":
+ case "w":
+ if (!lt.moveAfterClear("w")) {
+ return "You can't move while you're following someone.";
+ }
+ return null;
+ case "east":
+ case "e":
+ if (!lt.moveAfterClear("e")) {
+ return "You can't move while you're following someone.";
+ }
+ return null;
+ case "goto": {
+ int destX;
+ int destY;
+ try {
+ destX = Integer.parseInt(args.substring(0, args.lastIndexOf(' ')));
+ destY = Integer.parseInt(args.substring(args.lastIndexOf(' ') + 1));
+ } catch (Exception e) {
+ game.log.printError("parseCommand():" + lt.name + " tried to " + cmdline, e);
+ return null;
+ }
+ return lt.goTo(destX, destY, true);
+ }
+
+ case "addmember": {
+ if (lt.privs != 1)
+ return "Huh?";
+ if (args == null) {
+ return "Add who?";
+ }
+ LivingThing thnStore = game.getPlayer(args);
+ if (thnStore == null) {
+ return "They're not in this world";
+ }
+ if (lt.battle != null) {
+ return "Not while you're fighting!";
+ }
+ if (thnStore.battle != null) {
+ thnStore.chatMessage(lt.name + " has invited you to join their clan, but you are in the middle of a battle");
+ return "They're in the middle of a battle. They have been notified that you tried to clan them.";
+ }
+ lt.chatMessage("You have invited " + thnStore.name + " to join the clan " + lt.clan + ".");
+
+ if (true)
+ // FIXME: protocol implementation
+ throw new RuntimeException("cannot ask questions yet");
+ // FIXME: this looks dodgy
+ // FIXME: move to livingthing
+
+ thnStore.halt();
+ thnStore.stillThere(); // This puts something in the buffer
+ thnStore.stillThere(); // Have to do this twice to ensure that thnStore is out of
+ // its read loop
+ lt.connectionThread.sleep(500); // wait for the "notdead" response to get back from client.
+ try {
+ // Empty out the BufferedReader for the answer
+ // while (thnStore.instream.ready()) {
+ // thnStore.instream.read();
+ // }
+ } catch (Exception e) {
+ game.log.printError("parseCommand():While " + lt.name + " was trying to addmember " + thnStore.name, e);
+ }
+ thnStore.chatMessage(lt.name + " has invited you to join the clan " + lt.clan + ". If you accept, type yes.");
+ try {
+ if (thnStore.instream.readLine().equalsIgnoreCase("yes")) {
+ thnStore.clan = lt.clan;
+ if (thnStore.privs == 1) {
+ thnStore.privs = 0;
+ }
+ thnStore.chatMessage("You have been added to the clan, " + lt.clan + "");
+ thnStore.proceed();
+ game.removeDuskObject(thnStore);
+ game.addDuskObject(thnStore);
+ return thnStore.name + " has accepted your invitation.";
+ }
+ } catch (Exception e) {
+ game.log.printError("parseCommand():While reading the answer to " + lt.name + "'s attempt to addmember " + thnStore.name, e);
+ }
+ thnStore.proceed();
+ return thnStore.name + " has declined your invitation.";
+ }
+ case "kick": {
+ if (lt.privs != 1)
+ return "Huh?";
+ if (args == null) {
+ return "Kick who?";
+ }
+ LivingThing thnStore = game.getPlayer(args);
+ if (thnStore == null) {
+ return "They're not in this world.";
+ }
+ if (!thnStore.clan.equalsIgnoreCase(lt.clan)) {
+ return "They're not in your clan.";
+ }
+ thnStore.chatMessage("You have been kicked out of " + lt.clan + ".");
+ thnStore.clan = "none";
+ game.removeDuskObject(thnStore);
+ game.addDuskObject(thnStore);
+ return thnStore.name + " has been kicked out of your clan.";
+ }
+// if (lt.privs > 2) {
+// if (lt.privs > 4) {
+ case "makegod": {
+ if (lt.privs <= 4)
+ return "Huh?";
+
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ if (args == null) {
+ return "Make who a god?";
+ }
+ int iSPloc = args.indexOf(" ");
+ if (iSPloc < 0) {
+ return "Make them what level of a god?";
+ }
+ String sName = args.substring(0, iSPloc).trim();
+ int level = Integer.parseInt(args.substring(iSPloc).trim());
+
+ LivingThing thnStore = game.getPlayer(sName);
+ if (thnStore == null) {
+ return "They're not in this world.";
+ }
+ int oldLevel = thnStore.privs;
+ thnStore.privs = level;
+ thnStore.isSaveNeeded = true;
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":Changed " + thnStore.name + "'s priveledges from " + oldLevel + " to " + level + ".");
+ return thnStore.name + "'s priveledges have been set to " + level + ".";
+ }
+ case "reloadprefs": {
+ if (lt.privs <= 4)
+ return "Huh?";
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ game.loadPrefs();
+ return "Preferences reloaded";
+ }
+ case "resizemap":
+ if (lt.privs <= 4)
+ return "Huh?";
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ game.resizeMap(lt.x + 1, lt.y + 1);
+ return "Map resized";
+ case "shutdown":
+ if (lt.privs <= 4)
+ return "Huh?";
+ game.log.printMessage(Log.ALWAYS, lt.name + " has shut down the server.");
+ game.chatMessage("The server is going down.", "default");
+ game.blnShuttingDown = true;
+ for (LivingThing thnStore : game.playersByName.values()) {
+ try {
+ if (thnStore != lt) {
+ thnStore.close();
+ }
+ } catch (Exception e) {
+ if (thnStore != null) {
+ game.log.printError("parseCommand():While trying to close " + thnStore.name + " for " + lt.name + "'s shutdown request", e);
+ } else {
+ game.log.printError("parseCommand():While trying to close a null player for " + lt.name + "'s shutdown request", e);
+ }
+ }
+ }
+ lt.isSaveNeeded = true;
+ lt.savePlayer();
+ System.gc();
+ System.exit(0);
+ return null;
+ case "stop":
+ if (lt.privs <= 4)
+ return "Huh?";
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ game.blnShuttingDown = true;
+ return "Stopped accepting incoming socket connections.";
+ case "start":
+ if (lt.privs <= 4)
+ return "Huh?";
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ game.blnShuttingDown = false;
+ return "Started accepting incoming connections";
+ case "filteron":
+ if (lt.privs <= 4)
+ return "Huh?";
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ game.blnIPF = true;
+ return "Started filtering duplicate IP addressess of socket connections.";
+ case "filteroff":
+ if (lt.privs <= 4)
+ return "Huh?";
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ game.blnIPF = false;
+ return "Stopped filtering duplicate IP addressess of socket connections.";
+ case "floodlimit":
+ if (lt.privs <= 4)
+ return "Huh?";
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ if (args == null) {
+ return "What value do you want the floodlimit to have?";
+ }
+ try {
+ game.floodLimit = (long) Integer.parseInt(args);
+ return "Set floodlimit to " + args + " milliseconds.";
+ } catch (Exception e) {
+ game.log.printError("parseCommand():Invalid value \"" + args + "\" for floodlimit.", e);
+ return "Invalid value \"" + args + "\" for floodlimit.";
+ }
+ case "ipban": {
+ if (lt.privs <= 4)
+ return "Huh?";
+ String strBlockedIP;
+ if (args == null) {
+ return "Whos IP address do you wish to ban?";
+ }
+ LivingThing thnStore = game.getPlayer(args);
+ if (thnStore == null) {
+ return "They're not in this world.";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ String strIP = thnStore.getAddress();
+ int i = strIP.indexOf("/");
+ strIP = strIP.substring(i + 1, strIP.length());
+ // FIXME: better i/o
+ try (RandomAccessFile rafBannedIP = new RandomAccessFile("conf/blockedIP", "rw")) {
+ strBlockedIP = rafBannedIP.readLine();
+ while (strBlockedIP != null) {
+ if (strIP.indexOf(strBlockedIP) != -1) {
+ //rafBannedIP.close();
+ return "Already blocked.";
+ }
+ strBlockedIP = rafBannedIP.readLine();
+ }
+ rafBannedIP.seek(rafBannedIP.length());
+ rafBannedIP.writeBytes(strIP + "\n");
+ } catch (IOException ex) {
+ game.log.printError("parseCommand():When " + lt.name + " tried to ban " + thnStore + "'s IP address", ex);
+ }
+ return thnStore.name + "'s IP address has been blocked.";
+ }
+ case "loglevel":
+ if (lt.privs <= 4)
+ return "Huh?";
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ if (args == null) {
+ return "Logging level is currently " + game.log.getLogLevel();
+ }
+ try {
+ int level = Integer.parseInt(args);
+ game.log.setLogLevel(level);
+ return "Logging level is now " + game.log.getLogLevel();
+ } catch (Exception e) {
+ game.log.printError("parseCommand():Invalid value \"" + args + "\" for loglevel.", e);
+ return "Invalid value \"" + args + "\" for loglevel.";
+ }
+ case "gc":
+ if (lt.privs <= 4)
+ return "Huh?";
+ game.log.printMessage(Log.INFO, "Starting garbage collection.");
+ System.gc();
+ game.log.printMessage(Log.INFO, "Finished garbage collection.");
+ return "Finished garbage collection.";
+ case "finalize":
+ if (lt.privs <= 4)
+ return "Huh?";
+ game.log.printMessage(Log.INFO, "Starting finalization.");
+ System.runFinalization();
+ game.log.printMessage(Log.INFO, "Finished finalization.");
+ return "Finished finalization.";
+ case "cleanup":
+ if (lt.privs <= 4)
+ return "Huh?";
+ game.cleanup();
+ return "Finished cleanup.";
+ case "save":
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (game.blnSavingGame) {
+ return "Game already being saved, please wait.";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ game.saveMap();
+ return "Game settings saved";
+ case "backup":
+ if (lt.privs <= 2)
+ return "Huh?";
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ game.backupMap();
+ return "Game settings backed up";
+ case "list": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "What do you want to list?";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ cmdline = cmdline.substring(5);
+ String filename = null;
+ String strTitle = null;
+ if (args.equals("items")) {
+ filename = "defItems";
+ strTitle = "Items:\n";
+ } else if (args.equals("conf")) {
+ filename = "conf";
+ strTitle = "Conf files:\n";
+ } else if (args.equals("mobs")) {
+ filename = "defMobs";
+ strTitle = "Mobiles:\n";
+ } else if (args.equals("commands")) {
+ filename = "commands";
+ strTitle = "Custom commands:\n";
+ } else if (args.equals("races")) {
+ filename = "defRaces";
+ strTitle = "Races:\n";
+ } else if (args.equals("pets")) {
+ filename = "defPets";
+ strTitle = "Pets:\n";
+ } else if (args.equals("factions")) {
+ filename = "factions";
+ strTitle = "Factions:\n";
+ } else if (args.equals("conditions")) {
+ filename = "defConditions";
+ strTitle = "Conditions:\n";
+ } else if (args.equals("help")) {
+ filename = "helpFiles";
+ strTitle = "Help Files:\n";
+ } else if (args.equals("scripts")) {
+ filename = "scripts";
+ strTitle = "Scripts:\n";
+ } else if (args.equals("spell groups")) {
+ filename = "defSpellGroups";
+ strTitle = "Spell Groups:\n";
+ } else if (args.equals("spells")) {
+ filename = "defSpells";
+ strTitle = "Spells:\n";
+ } else if (args.equals("props")) {
+ filename = "defProps";
+ strTitle = "Props:\n";
+ } else if (args.equals("move actions")) {
+ filename = "defMoveActions";
+ strTitle = "Move Action Scripts:\n";
+ } else if (args.equals("can move")) {
+ filename = "defCanMoveScripts";
+ strTitle = "Can Move Scripts:\n";
+ } else if (args.equals("can see")) {
+ filename = "defCanSeeScripts";
+ strTitle = "Can See Scripts:\n";
+ } else if (args.equals("tile actions")) {
+ filename = "defTileActions";
+ strTitle = "Tile Action Scripts:\n";
+ } else if (args.equals("tile move")) {
+ filename = "defTileScripts";
+ strTitle = "Can Move Tile Scripts:\n";
+ } else if (args.equals("tile see")) {
+ filename = "defTileSeeScripts";
+ strTitle = "Tile See Scripts:\n";
+ }
+ if (filename != null) {
+ File filList = new File(filename);
+ String strResult[] = filList.list();
+ StringBuilder strBuff = new StringBuilder();
+ strBuff.append("").append((char) 20).append(strTitle).append("\n");
+ for (int i = 0; i < strResult.length; i++) {
+ // Only output files that do not end in .dsko
+ if (strResult[i].indexOf(".dsko") == -1) {
+ strBuff.append(strResult[i]).append("\n");
+ }
+ }
+ strBuff.append("--EOF--\n");
+ lt.send(strBuff.toString());
+ return null;
+ }
+ return "You can't list that.";
+ }
+ case "view": {
+ if (lt.privs <= 2)
+ return "Huh?";
+
+ if (args == null) {
+ return "What do you want to view?";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ if (args.indexOf("..") != -1) {
+ return "You don't have permission to access that file.";
+ }
+ String filename = null;
+ boolean blnUser = false;
+ boolean blnPet = false;
+ if (args.startsWith("item ")) {
+ args = args.toLowerCase();
+ filename = "defItems/" + args.substring(5);
+ } else if (args.startsWith("conf ")) {
+ filename = "conf/" + args.substring(5);
+ } else if (args.startsWith("mob ")) {
+ filename = "defMobs/" + args.substring(4);
+ } else if (args.startsWith("command ")) {
+ filename = "commands/" + args.substring(8);
+ } else if (args.startsWith("race ")) {
+ filename = "defRaces/" + args.substring(5);
+ } else if (args.startsWith("pet ")) {
+ filename = "defPets/" + args.substring(5);
+ } else if (args.startsWith("faction")) {
+ return "You cannot view faction files.";
+ } else if (args.startsWith("condition ")) {
+ filename = "defConditions/" + args.substring(10);
+ } else if (args.startsWith("help ")) {
+ filename = "helpFiles/" + args.substring(5);
+ } else if (args.startsWith("script ")) {
+ filename = "scripts/" + args.substring(7);
+ } else if (args.startsWith("spell group ")) {
+ filename = "defSpellGroups/" + args.substring(12);
+ } else if (args.startsWith("spell ")) {
+ filename = "defSpells/" + args.substring(6);
+ } else if (args.startsWith("prop ")) {
+ filename = "defProps/" + args.substring(5);
+ } else if (args.startsWith("move action ")) {
+ filename = "defMoveActions/" + args.substring(12);
+ } else if (args.startsWith("can move ")) {
+ filename = "defCanMoveScripts/" + args.substring(9);
+ } else if (args.startsWith("can see ")) {
+ filename = "defCanSeeScripts/" + args.substring(8);
+ } else if (args.startsWith("tile action ")) {
+ filename = "defTileActions/" + args.substring(12);
+ } else if (args.startsWith("tile move ")) {
+ filename = "defTileScripts/" + args.substring(10);
+ } else if (args.startsWith("tile see ")) {
+ filename = "defTileSeeScripts/" + args.substring(9);
+ } else if (args.startsWith("user ")) {
+ if (lt.privs < 5) {
+ return "You don't have enough privelages to edit a user's file.";
+ }
+ blnUser = true;
+ filename = "users/" + args.substring(5);
+ } else if (args.startsWith("pet ")) {
+ if (lt.privs < 5) {
+ return "You don't have enough privelages to edit a user's pet file.";
+ }
+ blnPet = true;
+ filename = "pets/" + args.substring(4);
+ }
+ File filView = new File(filename);
+ if (!filView.exists()) {
+ if (blnUser) {
+ return "There is no player named \"" + filView.getName() + "\".";
+ }
+ if (blnPet) {
+ return "The player named \"" + filView.getName() + "\" does not have a pet.";
+ }
+ lt.send((char) 18 + args + "\n--EOF--\n");
+ return null;
+ }
+ RandomAccessFile rafView = null;
+ StringBuffer strBuff = new StringBuffer();
+ try {
+ rafView = new RandomAccessFile(filView, "rw");
+ if (blnUser) {
+ rafView.readLine(); //Skip over users' password
+ }
+ String strStore2 = rafView.readLine();
+ strBuff.append((char) 18 + args + "\n");
+ while (strStore2 != null) {
+ strBuff.append(strStore2 + "\n");
+ strStore2 = rafView.readLine();
+ }
+ strBuff.append("--EOF--\n");
+ lt.send(strBuff.toString());
+ } catch (Exception e) {
+ game.log.printError("parseCommand():Reading file for " + filView.getName(), e);
+ }
+ try {
+ rafView.close();
+ } catch (Exception e) {
+ game.log.printError("parseCommand():Closing file after " + filView.getName(), e);
+ }
+ return null;
+ }
+ case "submit": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "What do you want to submit?";
+ }
+ if ((lt.privs < 4) && (!args.startsWith("mob "))) {
+ return "You are not allowed to submit files.";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ if (args.indexOf("..") != -1) {
+ return "You don't have permission to access that file.";
+ }
+ boolean compile = false;
+ boolean blnUser = false;
+ boolean blnPet = false;
+ String strFileName = null;
+ if (args.startsWith("item ") && (lt.privs > 3)) {
+ args = args.toLowerCase();
+ strFileName = "defItems/" + args.substring(5);
+ } else if (args.startsWith("conf ") && (lt.privs > 3)) {
+ strFileName = "conf/" + args.substring(5);
+ } else if (args.startsWith("mob ")) {
+ strFileName = "defMobs/" + args.substring(4);
+ } else if (args.startsWith("command ") && (lt.privs > 3)) {
+ strFileName = "commands/" + args.substring(8);
+ compile = true;
+ } else if (args.startsWith("race ") && (lt.privs > 3)) {
+ strFileName = "defRaces/" + args.substring(5);
+ } else if (args.startsWith("pet ") && (lt.privs > 3)) {
+ strFileName = "defPets/" + args.substring(4);
+ } else if (args.startsWith("faction") && (lt.privs > 3)) {
+ return "You cannot submit faction files.";
+ } else if (args.startsWith("condition ") && (lt.privs > 3)) {
+ strFileName = "defConditions/" + args.substring(10);
+ } else if (args.startsWith("help ") && (lt.privs > 3)) {
+ strFileName = "helpFiles/" + args.substring(5);
+ } else if (args.startsWith("script ") && (lt.privs > 3)) {
+ strFileName = "scripts/" + args.substring(7);
+ compile = true;
+ } else if (args.startsWith("spell group ") && (lt.privs > 3)) {
+ strFileName = "defSpellGroups/" + args.substring(12);
+ compile = true;
+ } else if (args.startsWith("spell ") && (lt.privs > 3)) {
+ strFileName = "defSpells/" + args.substring(6);
+ } else if (args.startsWith("prop ")) {
+ strFileName = "defProps/" + args.substring(5);
+ } else if (args.startsWith("move action ") && (lt.privs > 3)) {
+ strFileName = "defMoveActions/" + args.substring(12);
+ compile = true;
+ } else if (args.startsWith("can move ") && (lt.privs > 3)) {
+ strFileName = "defCanMoveScripts/" + args.substring(9);
+ compile = true;
+ } else if (args.startsWith("can see ") && (lt.privs > 3)) {
+ strFileName = "defCanSeeScripts/" + args.substring(8);
+ compile = true;
+ } else if (args.startsWith("tile action ") && (lt.privs > 3)) {
+ strFileName = "defTileActions/" + args.substring(12);
+ compile = true;
+ } else if (args.startsWith("tile move ") && (lt.privs > 3)) {
+ strFileName = "defTileScripts/" + args.substring(10);
+ compile = true;
+ } else if (args.startsWith("tile see ") && (lt.privs > 3)) {
+ strFileName = "defTileSeeScripts/" + args.substring(9);
+ compile = true;
+ } else if (args.startsWith("user ")) {
+ if (lt.privs < 5) {
+ return "You don't have enough privelages to submit a user's file.";
+ }
+ if (game.getPlayer(args.substring(5)) != null) {
+ return "You cannot submit a file for an active user.";
+ }
+ blnUser = true;
+ strFileName = "users/" + args.substring(5);
+ } else if (args.startsWith("pet ")) {
+ if (lt.privs < 5) {
+ return "You don't have enough privelages to submit a user's pet file.";
+ }
+ if (game.getPlayer(args.substring(4)) != null) {
+ return "You cannot submit a pet file for an active user.";
+ }
+ blnPet = true;
+ strFileName = "pets/" + args.substring(4);
+ }
+ if (strFileName == null) {
+ return "Cannot submit " + args;
+ }
+ File filView = null;
+ try {
+ filView = new File(strFileName);
+ } catch (Exception e) {
+ return "Cannot submit " + args + " (" + strFileName + ")";
+ }
+ RandomAccessFile rafView = null;
+ try {
+ if (blnUser) {
+ /*
+ Read in the user's password before deleting the file
+ */
+ rafView = new RandomAccessFile(filView, "r");
+ cmdline = rafView.readLine();
+ }
+ if (filView.exists()) {
+ filView.delete();
+ }
+ rafView = new RandomAccessFile(filView, "rw");
+ if (blnUser) {
+ /*
+ Write out the password for user files
+ */
+ rafView.writeBytes(cmdline + "\n");
+ }
+ cmdline = lt.instream.readLine();
+ while (!cmdline.equals("--EOF--")) {
+ rafView.writeBytes(cmdline + "\n");
+ cmdline = lt.instream.readLine();
+ }
+ rafView.close();
+ if (compile) {
+ Script scrStore = new Script(filView.getPath(), game, true);
+ scrStore.close();
+ }
+ if (blnUser || blnPet) {
+ /*
+ Delete the .backup file for users and pets
+ */
+ filView = new File(strFileName + ".backup");
+ if (filView.exists()) {
+ filView.delete();
+ }
+ }
+ } catch (Exception e) {
+ game.log.printError("parseCommand():While submitting file " + args + " (" + filView.getName() + ")", e);
+ try {
+ rafView.close();
+ } catch (Exception e2) {
+ game.log.printError("parseCommand():While closing file " + args + " (" + filView.getName() + ") after failed submit", e);
+ }
+ return "Error while trying to submit " + args + " (" + filView.getName() + ").";
+ }
+ return "Submit of " + args + " was successful.";
+ }
+ case "delete": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "What do you want to delete?";
+ }
+ if (lt.privs < 4) {
+ return "You are not allowed to delete files.";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ if (args.indexOf("..") != -1) {
+ return "You don't have permission to access that file.";
+ }
+ String filename = null;
+ String strReturn = null;
+ if (args.startsWith("item ")) {
+ filename = "defItems/" + args.substring(5);
+ strReturn = "item " + args.substring(5);
+ } else if (args.startsWith("conf ")) {
+ filename = "conf/" + args.substring(5);
+ strReturn = "conf " + args.substring(5);
+ } else if (args.startsWith("mob ")) {
+ filename = "defMobs/" + args.substring(4);
+ strReturn = "mob " + args.substring(4);
+ } else if (args.startsWith("command ")) {
+ filename = "commands/" + args.substring(8);
+ strReturn = "command " + args.substring(8);
+ } else if (args.startsWith("race ")) {
+ filename = "defRaces/" + args.substring(5);
+ strReturn = "race " + args.substring(5);
+ } else if (args.startsWith("pet ")) {
+ filename = "defPets/" + args.substring(4);
+ strReturn = "pet " + args.substring(4);
+ } else if (args.startsWith("faction")) {
+ return "You cannot delete faction files.";
+ } else if (args.startsWith("condition ")) {
+ filename = "defConditions/" + args.substring(8);
+ strReturn = "condition " + args.substring(8);
+ } else if (args.startsWith("help ")) {
+ filename = "helpFiles/" + args.substring(5);
+ strReturn = "help " + args.substring(5);
+ } else if (args.startsWith("script ")) {
+ filename = "scripts/" + args.substring(7);
+ strReturn = "script " + args.substring(7);
+ } else if (args.startsWith("spell group ")) {
+ filename = "defSpellGroups/" + args.substring(12);
+ strReturn = "spell group " + args.substring(12);
+ } else if (args.startsWith("spell ")) {
+ filename = "defSpells/" + args.substring(6);
+ strReturn = "spell " + args.substring(6);
+ } else if (args.startsWith("prop ")) {
+ filename = "defProps/" + args.substring(5);
+ strReturn = "prop " + args.substring(5);
+ } else if (args.startsWith("move action ")) {
+ filename = "defMoveActions/" + args.substring(12);
+ strReturn = "move action " + args.substring(12);
+ } else if (args.startsWith("can move ")) {
+ filename = "defCanMoveScripts/" + args.substring(9);
+ strReturn = "can move " + args.substring(9);
+ } else if (args.startsWith("can see ")) {
+ filename = "defCanSeeScripts/" + args.substring(8);
+ strReturn = "can see " + args.substring(8);
+ } else if (args.startsWith("tile action ")) {
+ filename = "defTileActions/" + args.substring(12);
+ strReturn = "tile action " + args.substring(12);
+ } else if (args.startsWith("tile move ")) {
+ filename = "defTileScripts/" + args.substring(10);
+ strReturn = "tile move " + args.substring(10);
+ } else if (args.startsWith("tile see ")) {
+ filename = "defTileSeeScripts/" + args.substring(9);
+ strReturn = "tile see " + args.substring(9);
+ }
+ File filDelete = null;
+ if (filename != null) {
+ filDelete = new File(filename);
+ if (filDelete.exists()) {
+ filDelete.delete();
+ filDelete = new File(filename + ".dsko");
+ if (filDelete.exists()) {
+ filDelete.delete();
+ strReturn += " and the associated .dsko file.";
+ }
+ } else {
+ return strReturn + " does not exist.";
+ }
+ return "Deleted " + strReturn;
+ }
+ return "You cannot delete that.";
+ }
+ case "clanleader": {
+ if (lt.privs <= 2)
+ return "Huh?";
+
+ if (args == null) {
+ return "Clanleader who?";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ LivingThing thnStore = game.getPlayer(args.substring(0, args.indexOf(' ')));
+ if (thnStore == null) {
+ return "They're not in this world";
+ }
+ if (args.length() < thnStore.name.length() + 2) {
+ return "What clan?";
+ }
+ if (thnStore.privs > 1) {
+ return "You can't clanleader them.";
+ }
+ args = args.substring(thnStore.name.length() + 1);
+ thnStore.clan = args;
+ if (args.equals("none")) {
+ thnStore.privs = 0;
+ thnStore.chatMessage("You are now clanless.");
+ } else {
+ thnStore.privs = 1;
+ thnStore.chatMessage("You are now a member of the " + args + " clan.");
+ }
+ game.removeDuskObject(thnStore);
+ game.addDuskObject(thnStore);
+ return thnStore.name + " is now a leader of the " + args + " clan.";
+ }
+ case "boot": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "Boot who?";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ LivingThing thnStore = game.getPlayer(args);
+ if (thnStore == null) {
+ return "They're not in this world.";
+ }
+ if (thnStore.privs >= lt.privs) {
+ thnStore.chatMessage(lt.name + " attempted to boot you.");
+ return "You do not have high enough privelages to boot them.";
+ }
+ thnStore.chatMessage("You have been booted.");
+ thnStore.close();
+ return null;
+ }
+ case "hardkill": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "HardKill who?";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ LivingThing thnStore = game.getPlayer(args);
+ if (thnStore == null) {
+ return "They're not in this world.";
+ }
+ if (thnStore.privs >= lt.privs) {
+ thnStore.chatMessage(lt.name + " attempted to HardKill you.");
+ return "You do not have high enough privelages to HardKill them.";
+ }
+ thnStore.closeNoMsgPlayer();
+ return null;
+ }
+ case "nochannel": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "nochannel who for how long?";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ LivingThing thnStore;
+ int duration;
+ try {
+ thnStore = game.getPlayer(args.substring(0, args.indexOf(" ")));
+ duration = Integer.parseInt(args.substring(args.indexOf(" ") + 1));
+ } catch (Exception e) {
+ game.log.printError("parseCommand():When " + lt.name + " tried to nochannel " + args, e);
+ return "nochannel who for how long?";
+ }
+ if (thnStore == null) {
+ return "They're not in this world.";
+ }
+ if (thnStore.privs >= lt.privs) {
+ thnStore.chatMessage(lt.name + " attempted to nochannel you.");
+ return "You do not have high enough privelages to nochannel them.";
+ }
+ if (duration > game.noChannelMax) {
+ duration = game.noChannelMax;
+ }
+ thnStore.chatMessage("You have been nochanneled for " + duration + " seconds.");
+ thnStore.noChannel = duration;
+ return "You have nochanneled " + thnStore.name + " for " + duration + " seconds";
+ }
+ case "allowchannel": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "allowchannel who?";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ LivingThing thnStore = game.getPlayer(args);
+ if (thnStore == null) {
+ return "They're not in this world.";
+ }
+ thnStore.chatMessage("Your nochannel status has been removed.");
+ thnStore.noChannel = 0;
+ return thnStore.name + "'s nochannel status has been removed.";
+ }
+ case "gecho": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "G-Echo what?";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ game.chatMessage(args, "default");
+ return null;
+ }
+ case "teleport": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "Teleport to where?";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ int index = args.lastIndexOf('_');
+ char charSep = ' ';
+ if (index != -1) {
+ charSep = '_';
+ }
+ try {
+ int destX = Integer.parseInt(args.substring(0, args.lastIndexOf(charSep)));
+ int destY = Integer.parseInt(args.substring(args.lastIndexOf(charSep) + 1));
+ if (lt.privs < 5 && destX >= game.map.getCols()) {
+ destX = game.map.getCols() - 1;
+ }
+ if (lt.privs < 5 && destY >= game.map.getRows()) {
+ destY = game.map.getRows() - 1;
+ }
+ if (destX < 0) {
+ destX = 0;
+ }
+ if (destY < 0) {
+ destY = 0;
+ }
+ lt.changeLocBypass(destX, destY);
+ } catch (Exception e) {
+ LivingThing thnStore = game.getPlayer(args);
+ if (thnStore == null) {
+ return "Teleport to where?";
+ } else {
+ int destX = thnStore.x;
+ int destY = thnStore.y;
+ if (lt.privs < 5 && destX > 349) {
+ destX = 349;
+ }
+ if (lt.privs < 5 && destY > 349) {
+ destY = 349;
+ }
+ if (destX < 0) {
+ destX = 0;
+ }
+ if (destY < 0) {
+ destY = 0;
+ }
+ lt.changeLocBypass(destX, destY);
+ }
+ }
+ return null;
+ }
+ case "remove": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "remove what?";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ DuskObject objStore = lt.getLocalObject(args);
+ if (objStore != null) {
+ if (objStore.isLivingThing()) {
+ LivingThing thnStore = (LivingThing) objStore;
+ if (thnStore.isMob()) {
+ thnStore.close();
+ game.blnMobListChanged = true;
+ return "Object removed.";
+ } else {
+ return "You can't remove players/pets.";
+ }
+ } else if (objStore.isItem()) {
+ //game.vctItems.remove(objStore);
+ game.removeDuskObject(objStore);
+ return "Object removed.";
+ } else if (objStore.isSign()) {
+ //game.vctSigns.remove(objStore);
+ //game.blnSignListChanged = true;
+ game.removeDuskObject(objStore);
+ return "Object removed.";
+ } else if (objStore.isProp()) {
+ //game.vctProps.removeElement(objStore);
+ //game.blnPropListChanged = true;
+ game.removeDuskObject(objStore);
+ return "Object removed.";
+ } else if (objStore.isMerchant()) {
+ //game.vctMerchants.remove(objStore);
+ //game.blnMerchantListChanged = true;
+ game.removeDuskObject(objStore);
+ return "Object removed.";
+ }
+ }
+ return "You don't see that here.";
+ }
+ case "changeclan": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "ChangeClan who?";
+ }
+ LivingThing thnStore = game.getPlayer(args.substring(0, args.indexOf(' ')));
+ if (thnStore == null) {
+ return "They're not in this world";
+ }
+ if (cmdline.length() < thnStore.name.length() + 2) {
+ return "What clan?";
+ }
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ args = args.substring(thnStore.name.length() + 1);
+ thnStore.clan = args;
+ if (thnStore.privs == 1) {
+ thnStore.privs = 0;
+ }
+ if (args.equals("none")) {
+ thnStore.chatMessage("You are now a member of no clan.");
+ } else {
+ thnStore.chatMessage("You are now a member of the " + args + " clan.");
+ }
+ return thnStore.name + " has been added to the " + args + " clan";
+ }
+ case "madd": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "Madd what?";
+ }
+ Merchant mrcStore = game.overMerchant(lt.x, lt.y);
+ if (mrcStore != null) {
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ mrcStore.items.add(args);
+ game.refreshEntities(lt);
+ } else {
+ if (game.overPlayerMerchant(lt.x, lt.y) != null) {
+ return "You cannot add items to a player's merchant this way.";
+ }
+ return "You are not on a merchant.";
+ }
+ return null;
+ }
+ case "mremove": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ if (args == null) {
+ return "Mremove what?";
+ }
+ Merchant mrcStore = game.overMerchant(lt.x, lt.y);
+ if (mrcStore != null) {
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+ mrcStore.items.remove(args);
+ game.refreshEntities(lt);
+ } else {
+ if (game.overPlayerMerchant(lt.x, lt.y) != null) {
+ return "You cannot remove items from a player's merchant this way.";
+ }
+ return "You are not on a merchant.";
+ }
+ return null;
+ }
+ case "whoip": {
+ if (lt.privs <= 2)
+ return "Huh?";
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":" + cmdline + ":" + lt.x + "," + lt.y);
+
+ int nPlayers = game.playersByName.size();
+ StringBuilder sb = new StringBuilder();
+
+ // TODO: this used to be atomic, does it need to be?
+
+ for (LivingThing thnStore : game.playersByName.values()) {
+ boolean hidden = false;
+ if (thnStore.privs > 2) {
+ if (thnStore.hasCondition("invis")) {
+ hidden = true;
+ }
+ }
+ if (hidden && (lt.privs < thnStore.privs)) {
+ nPlayers--;
+ }
+ }
+
+ lt.chatMessage("\tThere are " + nPlayers + " players online:");
+
+ for (LivingThing thnStore : game.playersByName.values()) {
+ boolean hidden = false;
+ boolean skip = false;
+ if (thnStore.privs > 2) {
+ if (thnStore.hasCondition("invis")) {
+ hidden = true;
+ }
+ }
+ if (hidden && (lt.privs < thnStore.privs)) {
+ skip = true;
+ }
+ if (!skip) {
+ String ip = thnStore.getAddress().toString();
+ while (ip.length() < 34) {
+ ip += " ";
+ }
+ sb.setLength(0);
+ sb.append(" ").append(ip);
+ sb.append(thnStore.getCharacterPoints()).append("cp ");
+ if (thnStore.privs == 1) {
+ sb.append("{Clan Leader}");
+ } else if (thnStore.privs == 3) {
+ sb.append("{God}");
+ } else if (thnStore.privs == 4) {
+ sb.append("{High God}");
+ } else if (thnStore.privs > 4) {
+ sb.append("{Master God}");
+ }
+ if (hidden) {
+ sb.append("{hidden}");
+ }
+ if (thnStore.noChannel != 0) {
+ sb.append("{nochanneled}");
+ }
+ if (!thnStore.clan.equals("none")) {
+ sb.append("<" + thnStore.clan + "> ");
+ }
+ sb.append(thnStore.name + "\n");
+ lt.chatMessage(sb.toString());
+ }
+ }
+
+ return null;
+ }
+ case "flee": {
+ if (lt.battle != null) {
+ lt.battle.addFirstCommand(lt, "flee");
+ return null;
+ } else {
+ return "You're not fighting anyone";
+ }
+ }
+ case "sleep": {
+ if (lt.isSleeping) {
+ return "You are already asleep";
+ }
+ if (lt.battle != null) {
+ return "Not while you're fighting!";
+ }
+ if (!(lt.getMaster() == null || lt.getMaster().isSleeping)) {
+ return "You can't sleep if you're following someone who's awake.";
+ }
+ lt.isSleeping = true;
+ lt.updateActions();
+ game.removeDuskObject(lt);
+ game.addDuskObject(lt);
+ return "You go to sleep";
+ }
+ case "wake": {
+ if (lt.isSleeping) {
+ lt.isSleeping = false;
+ lt.updateActions();
+ game.removeDuskObject(lt);
+ game.addDuskObject(lt);
+ return "You wake up";
+ } else {
+ return "You are already awake";
+ }
+ }
+ case "change": {
+ if (lt.battle != null) {
+ return "Not while you're fighting!";
+ }
+ if (args == null) {
+ return "Change what?";
+ }
+ if (args.equals("race")) {
+ if (lt.getCharacterPoints() > game.changeRaceCpLimit) {
+ return "You can no longer change your race.";
+ }
+ lt.unloadRace();
+
+ // FIXME: I'm not sure why this needs to clear messages here.
+
+ if (lt.isPet()) {
+
+ lt.getMaster().halt();
+ // lt.getMaster().stillThere(); // This puts something in the buffer
+ // lt.getMaster().thrConnection.sleep(750); // wait for it...
+ try {
+ // Empty out the BufferedReader for the answer
+ // while (lt.getMaster().instream.ready()) {
+ // lt.getMaster().instream.readLine();
+ // }
+ } catch (Exception e) {
+ game.log.printError("parseCommand():Trying to empty ready buffer of pet's master for change race.", e);
+ }
+ } else {
+ lt.halt();
+ // lt.stillThere(); // This puts something in the buffer
+ // lt.thrConnection.sleep(750); // wait for it...
+ try {
+ // Empty out the BufferedReader for the answer
+ // while (lt.instream.ready()) {
+ // lt.instream.readLine();
+ // }
+ } catch (Exception e) {
+ game.log.printError("parseCommand():Trying to empty ready buffer of player for change race.", e);
+ }
+ }
+ lt.loadRace();
+ if (lt.isPet()) {
+ lt.getMaster().proceed();
+ lt.getMaster().updateStats();
+ } else {
+ lt.proceed();
+ }
+ game.removeDuskObject(lt);
+ game.addDuskObject(lt);
+ lt.updateStats();
+ return "Your race has been changed.";
+ }
+ }
+ case "gossip": {
+ if (!lt.isPlayer()) {
+ return "Only players can use the gossip/clan/tell channels.";
+ }
+ if (lt.noChannel != 0) {
+ return "You can't do that when nochanneled.";
+ }
+ if (args == null) {
+ return "Gossip what?";
+ }
+ if (args.length() > game.messagecap) {
+ return "That message was too long.";
+ }
+ if (!args.equals("")) {
+ long lTemp = lt.lastMessageStamp;
+ lt.lastMessageStamp = System.currentTimeMillis();
+ if ((System.currentTimeMillis() - lTemp) < game.floodLimit) {
+ return "No flooding.";
+ }
+ String strPerson = lt.name;
+ if (lt.privs > 2
+ && lt.hasCondition("invis")
+ && lt.hasCondition("invis2")) {
+ strPerson = "A god";
+ }
+ game.chatMessage(strPerson + " gossips: " + args, lt.name);
+ }
+ return null;
+ }
+ case "clan": {
+ if (!lt.isPlayer() && !lt.isMob()) {
+ return "Only players can use the gossip/clan/tell channels.";
+ }
+ if (lt.clan.equals("none")) {
+ return "You're not in a clan. Use gossip instead";
+ }
+ if (lt.noChannel != 0) {
+ return "You can't do that when nochanneled.";
+ }
+ if (args == null) {
+ return "Clan what?";
+ }
+ if (args.length() > game.messagecap) {
+ return "That message was too long.";
+ }
+ if (!args.equals("")) {
+ long lTemp = lt.lastMessageStamp;
+ lt.lastMessageStamp = System.currentTimeMillis();
+ if ((System.currentTimeMillis() - lTemp) < game.floodLimit) {
+ return "No flooding.";
+ }
+ game.chatMessage(lt.name + " clans: " + args, lt.clan, lt.name);
+ }
+ return null;
+ }
+ case "say": {
+ if (args == null) {
+ return "Say what?";
+ }
+ if (lt.noChannel != 0) {
+ return "You can't do that when nochanneled.";
+ }
+ if (args.length() > game.messagecap) {
+ return "That message was too long.";
+ }
+ if (!args.equals("")) {
+ if (lt.isPet()) {
+ game.chatMessage("Pet " + lt.name + " says: " + args, lt.x, lt.y, lt.name);
+ } else if (lt.isMob()) {
+ game.chatMessage("Mob " + lt.name + " says: " + args, lt.x, lt.y, "default");
+ } else {
+ long lTemp = lt.lastMessageStamp;
+ lt.lastMessageStamp = System.currentTimeMillis();
+ if ((System.currentTimeMillis() - lTemp) < game.floodLimit) {
+ return "No flooding.";
+ }
+ String strPerson = lt.name;
+ if (lt.privs > 2
+ && lt.hasCondition("invis")
+ && lt.hasCondition("invis2")) {
+ strPerson = "A god";
+ }
+ game.chatMessage(strPerson + " says: " + args, lt.x, lt.y, lt.name);
+ }
+ }
+ return null;
+ }
+ case "emote": {
+ if (args == null) {
+ return "Emote what?";
+ }
+ if (lt.noChannel != 0) {
+ return "You can't do that when nochanneled.";
+ }
+ if (args.length() > game.messagecap) {
+ return "That message was too long.";
+ }
+ if (!args.equals("")) {
+ long lTemp = lt.lastMessageStamp;
+ lt.lastMessageStamp = System.currentTimeMillis();
+ if ((System.currentTimeMillis() - lTemp) < game.floodLimit) {
+ return "No flooding.";
+ }
+ String strPerson = lt.name;
+ if (lt.privs > 2
+ && lt.hasCondition("invis")
+ && lt.hasCondition("invis2")) {
+ strPerson = "A god";
+ }
+ game.chatMessage(strPerson + " " + args, lt.x, lt.y, lt.name);
+ }
+ return null;
+ }
+ case "tell": {
+ if (!lt.isPlayer()) {
+ return "Only players can use the gossip/clan/tell channels.";
+ }
+ if (args == null) {
+ return "Tell who what?";
+ }
+ if (lt.noChannel != 0) {
+ return "You can't do that when nochanneled.";
+ }
+ StringTokenizer tknStore = new StringTokenizer(args, " ");
+ String strStore2 = null;
+ try {
+ strStore2 = tknStore.nextToken();
+ } catch (Exception e) {
+ return "Tell who?";
+ }
+ LivingThing thnStore = game.getPlayer(strStore2);
+ if (thnStore == null) {
+ return "They're not in this world.";
+ }
+ if (thnStore.privs > 2
+ && thnStore.hasCondition("invis")
+ && thnStore.hasCondition("invis2")) {
+ return "They're not in this world.";
+ }
+ if (thnStore.name.equalsIgnoreCase(lt.name)) {
+ return "Talking to yourself is not a good sign.";
+ }
+ String strIgnoreName = thnStore.name.toLowerCase();
+ if (lt.ignoreList.contains(strIgnoreName)) {
+ return "You can't do that while you are ignoring them.";
+ }
+ strIgnoreName = lt.name.toLowerCase();
+ if (thnStore.ignoreList.contains(strIgnoreName)) {
+ return "They did not get the message, they are ignoring you.";
+ }
+ args = args.substring(strStore2.length(), args.length()).trim();
+ if (args.length() > game.messagecap) {
+ return "That message was too long.";
+ }
+ if (args.length() == 0) {
+ return "Tell them what?";
+ }
+ long lTemp = lt.lastMessageStamp;
+ lt.lastMessageStamp = System.currentTimeMillis();
+ if ((System.currentTimeMillis() - lTemp) < game.floodLimit) {
+ return "No flooding.";
+ }
+ String strPerson = lt.name;
+ if (lt.privs > 2
+ && lt.hasCondition("invis")
+ && lt.hasCondition("invis2")) {
+ strPerson = "A god";
+ }
+ game.log.printMessage(Log.ALWAYS, lt.name + " tells " + thnStore.name + " : " + args);
+ thnStore.chatMessage(strPerson + " tells you: " + args);
+ return "You tell " + strStore2 + ": " + args;
+ }
+ case "who": {
+ int nPlayers = game.playersByName.size();
+ StringBuilder sb = new StringBuilder();
+
+ // TOOD: originally this was atomic on stream
+ // although 'atomic' is wrong since nobody else was atomic on stream
+
+ for (LivingThing thnStore : game.playersByName.values()) {
+ boolean hidden = false;
+ if (thnStore.privs > 2) {
+ if (thnStore.hasCondition("invis")) {
+ hidden = true;
+ }
+ }
+ if (hidden && (lt.privs < thnStore.privs)) {
+ nPlayers--;
+ }
+ if (lt.privs < 3 && !thnStore.isWorking) {
+ nPlayers--;
+ }
+ if (lt.privs < 3 && !thnStore.isReady) {
+ nPlayers--;
+ }
+ }
+
+ lt.chatMessage("\tThere are " + nPlayers + " players online:");
+
+ for (LivingThing thnStore : game.playersByName.values()) {
+ boolean hidden = false;
+ boolean skip = false;
+ if (thnStore.privs > 2) {
+ if (thnStore.hasCondition("invis")) {
+ hidden = true;
+ }
+ }
+ if (hidden && (lt.privs < thnStore.privs)) {
+ skip = true;
+ }
+ if (lt.privs < 3 && !thnStore.isWorking) {
+ skip = true;
+ }
+ if (lt.privs < 3 && !thnStore.isReady) {
+ skip = true;
+ }
+ System.out.println(" user " + thnStore.name + " skip " + skip);
+ if (!skip) {
+ sb.setLength(0);
+ sb.append("\t");
+ sb.append(thnStore.getCharacterPoints());
+ sb.append("cp ");
+ if (lt.privs > 2 && !thnStore.isWorking) {
+ sb.append("{* Not Working *}");
+ }
+ if (lt.privs > 2 && !thnStore.isReady) {
+ sb.append("{Entering the world}");
+ }
+ if (lt.privs > 2 && !thnStore.isSaveable) {
+ sb.append("{Loading/Saving}");
+ }
+ if (thnStore.privs == 1) {
+ sb.append("{Clan Leader}");
+ } else if (thnStore.privs == 3) {
+ sb.append("{God}");
+ } else if (thnStore.privs == 4) {
+ sb.append("{High God}");
+ } else if (thnStore.privs > 4) {
+ sb.append("{Master God}");
+ }
+ if (hidden) {
+ sb.append("{hidden}");
+ }
+ if (thnStore.noChannel != 0) {
+ sb.append("{nochanneled}");
+ }
+ if (thnStore.ignoreList.contains(lt.name.toLowerCase())) {
+ sb.append("{Ignoring you}");
+ }
+ if (lt.ignoreList.contains(thnStore.name.toLowerCase())) {
+ sb.append("{Ignored}");
+ }
+ if (!thnStore.clan.equals("none")) {
+ sb.append("<");
+ sb.append(thnStore.clan);
+ sb.append("> ");
+ }
+ if (thnStore.title == null
+ || thnStore.title.equals("none")) {
+ sb.append(thnStore.name);
+ //sb.append("\n");
+ } else {
+ sb.append(thnStore.name);
+ sb.append(" ");
+ sb.append(thnStore.title);
+ //sb.append("\n");
+ }
+ lt.chatMessage(sb.toString());
+ }
+ }
+ return "Who complete.";
+ }
+ case "kill":
+ case "attack":
+ case "a": {
+ if (args == null) {
+ return "Attack what?";
+ }
+ if (lt.isSleeping) {
+ return "You can't do that while you're sleeping";
+ }
+ DuskObject objStore = lt.getLocalObject(args);
+ if (objStore == null) {
+ return "You don't see that here.";
+ }
+ if (!objStore.isLivingThing()) {
+ return "You can't fight that.";
+ }
+ game.newBattle(lt, (LivingThing) objStore);
+ return null;
+ }
+ case "order": {
+ if (args == null) {
+ return "Order who to do what?";
+ }
+ int intStore = args.indexOf(" ");
+ if (intStore == -1) {
+ return "Order them to do what?";
+ }
+ DuskObject objStore = lt.getLocalObject(args.substring(0, intStore));
+ if (objStore == null) {
+ return "You don't see that here.";
+ }
+ if (!objStore.isLivingThing()) {
+ return "You can't order that.";
+ }
+ LivingThing thnStore = (LivingThing) objStore;
+ if (thnStore.getCharmer() != lt) {
+ return "They don't take orders from you.";
+ }
+ args = args.substring(intStore + 1);
+ try {
+ thnStore.chatMessage(Commands.parseCommand(thnStore, game, args));
+// lt.chatMessage(Commands.parseCommand(thnStore, engGame, strArgs));
+ } catch (Exception e) {
+ game.log.printError("parseCommand():" + thnStore.name + ", while trying to follow the following order: \"" + args + "\"", e);
+ }
+ return null;
+ }
+
+ case "look": {
+ if (args == null) {
+ return "Look at what?";
+ }
+ if (lt.isSleeping) {
+ return "You can't do that while you're sleeping";
+ }
+ DuskObject objStore = lt.getLocalObject(args);
+ if (objStore != null) {
+ if (objStore.isLivingThing()) {
+ LivingThing thnStore = (LivingThing) objStore;
+ thnStore.chatMessage(lt.name + " is looking at you.");
+ lt.chatMessage(thnStore.name + " has " + thnStore.getCharacterPoints() + "cp and " + thnStore.hp + "/" + thnStore.maxhp + "hp.");
+ if (thnStore.description != null) {
+ lt.chatMessage("Their description is: " + thnStore.description);
+ }
+ final String[] formats = {
+ "They are wielding %s.",
+ "They are wearing %s on their arms.",
+ "They are wearing %s on their legs.",
+ "They are wearing %s on their torso.",
+ "They are wearing %s on their waist.",
+ "They are wearing %s on their neck.",
+ "They are wearing %s on their skull.",
+ "They are wearing %s on their eyes.",
+ "They are wearing %s on their hands."
+ };
+ for (int i = 0; i < formats.length; i++) {
+ Item item = thnStore.wornItems.getWorn(i);
+ if (item != null)
+ lt.chatMessage(String.format(formats[i], item.description));
+ }
+ return null;
+ } else if (objStore.isItem()) {
+ Item itmStore = (Item) objStore;
+ return "You see " + itmStore.description + ".";
+ } else if (objStore.isProp()) {
+ Prop prpStore = (Prop) objStore;
+ return "You see " + prpStore.description + ".";
+ } else if (objStore.isSign()) {
+ Sign sgnStore = (Sign) objStore;
+ return "The sign says " + sgnStore.strMessage + ".";
+ } else if (objStore.isPlayerMerchant()) {
+ lt.chatMessage("You see a merchant that sells");
+ PlayerMerchant pmrStore = (PlayerMerchant) objStore;
+ boolean blnEmptyMerchant = true;
+ for (LinkedList<Item> list : pmrStore.vctItems.values()) {
+ Item item = (Item) list.element();
+ cmdline = item.name;
+ String strSpacer = "\t";
+ if (cmdline.length() < 11) {
+ strSpacer = "\t\t";
+ }
+ lt.chatMessage("\t" + cmdline + strSpacer + item.description);
+ blnEmptyMerchant = false;
+ }
+ if (blnEmptyMerchant) {
+ lt.chatMessage("\tNothing at the moment.");
+ }
+ } else if (objStore.isMerchant()) {
+ lt.chatMessage("You see a merchant that sells");
+ Merchant mrcStore = (Merchant) objStore;
+ boolean blnEmptyMerchant = true;
+ for (String item : mrcStore.items) {
+ Item itmStore = game.getItem(item);
+ if (itmStore != null) {
+ String strSpacer = "\t";
+ if (item.length() < 11) {
+ strSpacer = "\t\t";
+ }
+ lt.chatMessage("\t" + item + strSpacer + itmStore.description);
+ blnEmptyMerchant = false;
+ } else {
+ if (item.equals("pet")) {
+ lt.chatMessage("\tpets.");
+ blnEmptyMerchant = false;
+ } else {
+ item = item.substring(6, item.length());
+ lt.chatMessage("\ttraining in " + item);
+ blnEmptyMerchant = false;
+ }
+ }
+ }
+ if (blnEmptyMerchant) {
+ lt.chatMessage("\tNothing.");
+ }
+ return null;
+ }
+ }
+ return "You don't see that here.";
+ }
+
+ case "inv":
+ case "inventory": {
+ final String[] formats = {
+ "Wielded: %s",
+ "Arms: %s",
+ "Legs: %s",
+ "Torso: %s",
+ "Waist: %s",
+ "Neck: %s",
+ "Skull: %s",
+ "Eyes: %s",
+ "Hands: %s"};
+ lt.chatMessage("-Worn-");
+ for (int i = 0; i < formats.length; i++) {
+ Item item = lt.wornItems.getWorn(i);
+ if (item != null)
+ lt.chatMessage(String.format(formats[i], item.description));
+ }
+ lt.chatMessage("-Inventory-:");
+ for (LinkedList<Item> list : lt.itemList.values()) {
+ if (!list.isEmpty()) {
+ Item item = (Item) list.element();
+ lt.chatMessage(list.size() + " " + item.name);
+ }
+ }
+ return null;
+ }
+
+ case "help": {
+ File file;
+ String title;
+
+ // FIXME: was atomic
+ if (args == null) {
+ file = new File("help");
+ title = "Help";
+ } else {
+ if (args.indexOf("..") != -1) {
+ return "There is no help on that subject";
+ }
+ file = new File("helpFiles/" + args);
+ title = "Help on " + args;
+ }
+
+ try (RandomAccessFile helpFile = new RandomAccessFile(file, "r")) {
+ lt.chatMessage(title);
+ while ((cmdline = helpFile.readLine()) != null) {
+ lt.chatMessage(cmdline);
+ }
+ } catch (IOException e) {
+ game.log.printError("parseCommand():When " + lt.name + " tried to get help on " + args, e);
+ return "There is no help on that subject";
+ }
+ return null;
+ }
+
+ case "get": {
+ if (args == null) {
+ return "Get what?";
+ }
+ DuskObject objStore = lt.getLocalObject(args);
+ if (objStore == null) {
+ return "You don't see that here.";
+ }
+ if (!objStore.isItem()) {
+ return "You can't get that.";
+ }
+ Item itmStore = (Item) objStore;
+ if (Math.abs(lt.x - itmStore.x) + Math.abs(lt.y - itmStore.y) < 2) {
+ if (lt.privs > 2) {
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":gets " + args + ":" + lt.x + "," + lt.y);
+ }
+ lt.itemList.addElement(itmStore);
+ lt.updateItems();
+ game.removeDuskObject(itmStore);
+ } else {
+ return "That's too far away.";
+ }
+ itmStore.onGetItem(game, lt);
+ return null;
+ }
+
+ case "drop": {
+ if (args == null) {
+ return "Drop what?";
+ }
+ int intDot = args.indexOf(".");
+ int intNumToDrop = 1;
+ if (intDot != -1) {
+ try {
+ intNumToDrop = Integer.parseInt(args.substring(0, intDot));
+ } catch (NumberFormatException e) {
+ intNumToDrop = 1;
+ }
+ }
+ Item itmStore = lt.getItem(args);
+ if (itmStore != null) {
+ String strMessage = "You drop " + itmStore.name + ".";
+ if (intNumToDrop > 1) {
+ strMessage = "You drop " + intNumToDrop + " " + itmStore.name + ".";
+ }
+ if (itmStore.intCost == 0) {
+ strMessage = "A " + itmStore.name + " vanishes into thin air.";
+ if (intNumToDrop > 1) {
+ strMessage = intNumToDrop + " " + itmStore.name + " vanish into thin air.";
+ }
+ }
+ if (lt.privs > 2) {
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":drops " + args + ":" + lt.x + "," + lt.y);
+ }
+ for (int i = 0; i < intNumToDrop; i++) {
+ itmStore = lt.getItemAndRemove(itmStore.name);
+ itmStore.x = lt.x;
+ itmStore.y = lt.y;
+ if (itmStore.intCost != 0) {
+ //game.vctItems.add(itmStore);
+ game.addDuskObject(itmStore);
+ lt.updateItems();
+ }
+ itmStore.onDropItem(game, lt);
+ }
+ return strMessage;
+ }
+ return "You don't have that.";
+ }
+
+ case "use": {
+ if (args == null) {
+ return "Use what?";
+ }
+ if (lt.battle == null) {
+ lt.useItem(args, -1);
+ } else {
+ lt.battle.addCommand(lt, "use " + args);
+ }
+ return null;
+ }
+ case "eat": {
+ if (args == null) {
+ return "Eat what?";
+ }
+ if (lt.battle == null) {
+ lt.useItem(args, Item.FOOD);
+ } else {
+ lt.battle.addCommand(lt, "eat " + args);
+ }
+ return null;
+ }
+ case "drink": {
+ if (args == null) {
+ return "Drink what?";
+ }
+ if (lt.battle == null) {
+ lt.useItem(args, Item.DRINK);
+ } else {
+ lt.battle.addCommand(lt, "drink " + args);
+ }
+ return null;
+ }
+
+ case "give": {
+ if (args == null) {
+ return "Give who what?";
+ }
+ StringTokenizer tknStore = new StringTokenizer(args, " ");
+ String strStore2 = null;
+ try {
+ strStore2 = tknStore.nextToken();
+ } catch (Exception e) {
+ return "Give who what?";
+ }
+ DuskObject objStore = lt.getLocalObject(strStore2);
+ if (objStore == null) {
+ return "You don't see them here.";
+ }
+ if (!objStore.isLivingThing()) {
+ return "You can't give to that.";
+ }
+ LivingThing thnStore = (LivingThing) objStore;
+ if ((lt.privs < 3) && (Math.abs(thnStore.x - lt.x) + Math.abs(thnStore.y - lt.y) > 1)) {
+ return "They're too far away.";
+ }
+ args = args.substring(strStore2.length() + 1);
+ if (lt.privs > 2) {
+ game.log.printMessage(Log.INFO, "godcommand:" + lt.name + ":gives " + args + " to " + strStore2 + ":" + lt.x + "," + lt.y);
+ }
+ if (args.startsWith("gp")) {
+ args = args.substring(3);
+ try {
+ int intStore = Integer.parseInt(args);
+ if (intStore < 0) {
+ return "You can't give negative money!";
+ }
+ if (intStore <= lt.cash) {
+ lt.cash -= intStore;
+ thnStore.cash += intStore;
+ lt.updateStats();
+ thnStore.updateStats();
+ thnStore.chatMessage(lt.name + " gives you " + intStore + "gp.");
+ return "You give " + thnStore.name + " " + intStore + "gp.";
+ } else {
+ lt.chatMessage("You don't have that much gp");
+ }
+ } catch (Exception e) {
+ return "That is not a valid amount of gp to give.";
+ }
+ }
+ int intDot = args.indexOf(".");
+ int intNumToGive = 1;
+ if (intDot != -1) {
+ try {
+ intNumToGive = Integer.parseInt(args.substring(0, intDot));
+ } catch (NumberFormatException e) {
+ intNumToGive = 1;
+ }
+ }
+ Item itmStore = lt.getItem(args);
+ if (itmStore != null) {
+ String strMessage = lt.name + " gives you ";
+ String strMessage2 = "You give " + thnStore.name + " ";
+ if (intNumToGive > 1) {
+ strMessage += intNumToGive + " ";
+ strMessage2 += intNumToGive + " ";
+ }
+ strMessage += itmStore.name + ".";
+ strMessage2 += itmStore.name + ".";
+ cmdline = itmStore.name;
+
+ while (intNumToGive > 0) {
+ itmStore = lt.getItemAndRemove(cmdline);
+ thnStore.itemList.addElement(itmStore);
+ intNumToGive--;
+
+ itmStore.onDropItem(game, lt);
+ itmStore.onGetItem(game, thnStore);
+ }
+
+ thnStore.chatMessage(strMessage);
+ thnStore.updateItems();
+ lt.updateItems();
+ return strMessage2;
+ }
+ return "You don't have that.";
+ }
+
+ case "buy": {
+ if (args == null) {
+ return "Buy what?";
+ }
+ int quantity;
+ try {
+ int i = args.indexOf(" ");
+ quantity = Integer.parseInt(args.substring(0, i));
+ args = args.substring(i + 1);
+ } catch (Exception e) {
+ return "How many of what do you want to buy?";
+ }
+ if (quantity > 100) {
+ quantity = 100;
+ } else if (quantity < 1) {
+ return "You can't buy less than one of something.";
+ }
+ PlayerMerchant pmrStore = game.overPlayerMerchant(lt.x, lt.y);
+ if (pmrStore != null) {
+ long numItem = pmrStore.contains(args);
+ if (numItem > 0) {
+ Item itmStore = game.getItem(args);
+ if (itmStore != null) {
+ if (quantity > numItem) {
+ return "This merchant does not have that many.";
+ }
+ int intCost = (itmStore.intCost * 3) / 4;
+ if (lt.name.equalsIgnoreCase(pmrStore.strOwner)) {
+ intCost = 0;
+ }
+ if (intCost * quantity > lt.cash) {
+ return "You can't afford that";
+ } else {
+ lt.cash -= intCost * quantity;
+ pmrStore.cash += intCost * quantity;
+ itmStore = pmrStore.remove(args);
+ lt.itemList.addElement(itmStore);
+ for (int i = 1; i < quantity; i++) {
+ itmStore = pmrStore.remove(args);
+ lt.itemList.addElement(itmStore);
+ }
+ lt.updateItems();
+ lt.updateStats();
+ }
+ }
+ }
+ }
+
+ Merchant mrcStore = game.overMerchant(lt.x, lt.y);
+ if (mrcStore == null) {
+ return "Buy from whom?";
+ }
+ if (lt.getFollowing() != null && lt.getFollowing().isPet()) {
+ if (args.startsWith(lt.getFollowing().name + ":")) {
+ args = args.substring(lt.getFollowing().name.length() + 1);
+ if (mrcStore.contains(args)) {
+ if (args.startsWith("train:")) {
+ args = args.substring(6);
+ mrcStore.train(args, quantity, lt.getFollowing());
+ lt.updateStats();
+ }
+ }
+ return null;
+ }
+ }
+ if (mrcStore.contains(args)) {
+ if (args.startsWith("train:")) {
+ args = args.substring(6);
+ mrcStore.train(args, quantity, lt);
+ lt.updateStats();
+ } else {
+ if (args.startsWith("pet")) {
+ mrcStore.pet(lt);
+ lt.updateStats();
+ } else {
+ Item itmStore = game.getItem(args);
+ if (itmStore != null) {
+ if (itmStore.intCost * quantity > lt.cash) {
+ return "You can't afford that";
+ } else {
+ lt.cash -= itmStore.intCost * quantity;
+ lt.itemList.addElement(itmStore);
+ for (int i = 1; i < quantity; i++) {
+ lt.itemList.addElement(game.getItem(args));
+ }
+ lt.updateItems();
+ lt.updateStats();
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ case "sell": {
+ if (args == null) {
+ return "Sell what?";
+ }
+
+ PlayerMerchant pmrStore = game.overPlayerMerchant(lt.x, lt.y);
+ if (pmrStore != null) {
+ if (lt.name.equalsIgnoreCase(pmrStore.strOwner)) {
+ int quantity = 1;
+ try {
+ int i = args.indexOf(" ");
+ quantity = Integer.parseInt(args.substring(0, i));
+ args = args.substring(i + 1);
+ } catch (Exception e) {
+ return "How many of what do you want to sell?";
+ }
+ Item itmStore = lt.getItem(args);
+ for (int i = 0; i < quantity; i++) {
+ itmStore = lt.getItemAndRemove(args);
+ if (itmStore != null) {
+ itmStore.onDropItem(game, lt);
+ pmrStore.add(itmStore);
+ lt.isSaveNeeded = true;
+ } else {
+ i = quantity;
+ }
+ }
+ lt.updateItems();
+ lt.updateStats();
+ return null;
+ }
+ return "You cannot sell items to this merchant.";
+ }
+
+ Merchant mrcStore = game.overMerchant(lt.x, lt.y);
+ if (mrcStore == null) {
+ return "Sell that to whom?";
+ }
+ int quantity = 1;
+ try {
+ int i = args.indexOf(" ");
+ quantity = Integer.parseInt(args.substring(0, i));
+ args = args.substring(i + 1);
+ } catch (Exception e) {
+ return "How many of what do you want to sell?";
+ }
+ if (quantity > 100) {
+ quantity = 100;
+ }
+ Item itmStore = lt.getItem(args);
+ for (int i = 0; i < quantity; i++) {
+ itmStore = lt.getItemAndRemove(args);
+ if (itmStore != null) {
+ itmStore.onDropItem(game, lt);
+ lt.cash += (itmStore.intCost / 2);
+ lt.isSaveNeeded = true;
+ } else {
+ i = quantity;
+ }
+ }
+ lt.updateItems();
+ lt.updateStats();
+ return null;
+ }
+
+ case "cast": {
+ if (args == null) {
+ return "Cast what?";
+ }
+ if (lt.battle == null) {
+ lt.castSpell(args);
+ } else {
+ lt.battle.addCommand(lt, "cast " + args);;
+ }
+ return null;
+ }
+
+ case "follow": {
+ if (args == null) {
+ return "Follow who?";
+ }
+ if (lt.isSleeping) {
+ return "You can't do that while you're sleeping";
+ }
+ DuskObject objStore = lt.getLocalObject(args);
+ if (objStore == null) {
+ return "You don't see that here.";
+ }
+ if (objStore.isLivingThing()) {
+ LivingThing thnStore = (LivingThing) objStore;
+ if (lt.getMaster() != null && thnStore != lt.getMaster()) {
+ if (lt.isPet()) {
+ return "You can only follow your owner.";
+ }
+ return "You're already following someone. Leave them first.";
+ }
+ if (Math.abs(lt.x - thnStore.x) + Math.abs(lt.y - thnStore.y) > 1) {
+ return "They're too far away.";
+ }
+ if (thnStore == lt) {
+ return "You can't follow yourself.";
+ }
+ if (!thnStore.isPlayer() && !lt.isMob()) {
+ return "You can only follow players.";
+ }
+ if (thnStore.noFollow || (thnStore.isPet() && thnStore.getMaster().noFollow)) {
+ return "They won't let you follow them.";
+ }
+ if (lt.isPet()) {
+ thnStore.setFollowing(lt);
+ lt.setMaster(thnStore);
+ thnStore.updateStats();
+ lt.updateStats();
+ return "You are now following " + lt.getMaster().name + ".";
+ }
+ LivingThing thnStore2 = thnStore;
+ while (thnStore2 != null) {
+ if (lt == thnStore2) {
+ return "You're already in that group.";
+ }
+ thnStore2 = thnStore2.getMaster();
+ }
+ thnStore.chatMessage("You are now being followed by " + lt.name + ".");
+ while (thnStore.getFollowing() != null) {
+ thnStore = thnStore.getFollowing();
+ if (thnStore.isPlayer()) {
+ thnStore.chatMessage("You are now being followed by " + lt.name + ".");
+ }
+ }
+ thnStore.setFollowing(lt);
+ lt.setMaster(thnStore);
+ thnStore.updateStats();
+ lt.updateStats();
+ return "You are now following " + lt.getMaster().name + ".";
+ }
+ return "That's not something you can follow.";
+ }
+
+ case "unfollow": {
+ if (args == null) {
+ return "Unfollow who?";
+ }
+ LivingThing thnStore = lt.getFollowing();
+ if (thnStore != null && thnStore.isPet()) {
+ if (thnStore.name.equalsIgnoreCase(args)) {
+ lt.halt();
+ lt.chatMessage("Do you really want to permanently erase your pet?");
+ try {
+ if (lt.instream.readLine().equalsIgnoreCase("yes")) {
+ lt.getFollowing().close();
+ File deleteme = new File("pets/" + lt.name.toLowerCase());
+ deleteme.delete();
+ deleteme = new File("pets/" + lt.name.toLowerCase() + ".backup");
+ deleteme.delete();
+ lt.getFollowing().close();
+ lt.setFollowing(lt.getFollowing().getFollowing());
+ lt.proceed();
+ return "Your pet has been erased.";
+ }
+ } catch (Exception e) {
+ game.log.printError("parseCommand():While unfollowing pet for " + lt.name, e);
+ }
+ lt.proceed();
+ return null;
+ }
+ thnStore = thnStore.getFollowing();
+ }
+ while (thnStore != null) {
+ if (thnStore.name.equalsIgnoreCase(args)) {
+ if (thnStore.isPet()) {
+ thnStore = thnStore.getMaster();
+ }
+ thnStore.removeFromGroup();
+ return null;
+ }
+ thnStore = thnStore.getFollowing();
+ }
+ return "They're not following you.";
+ }
+
+ case "stay": {
+ if (lt.isPet()) {
+ lt.removeFromGroup();
+ return Commands.parseCommand(lt, game, "emote sits down to await " + lt.getMaster().name + "'s return.");
+ }
+ return (Commands.parseCommand(lt, game, "emote stays like a good little puppy."));
+ }
+
+ case "leave": {
+ if (lt.isPet()) {
+ return "You cannot leave your master unless he unfollows you.";
+ }
+ lt.removeFromGroup();
+ return "You are now on your own.";
+ }
+
+ case "unclan": {
+ if (lt.clan.equals("none")) {
+ return "You're not in a clan.";
+ }
+ if (lt.battle != null) {
+ return "Wait until you're done battling.";
+ }
+ try {
+ lt.halt();
+ lt.chatMessage("Are you sure you want to drop out of your clan? If so type yes.");
+ if (lt.instream.readLine().equalsIgnoreCase("yes")) {
+ lt.clan = "none";
+ if (lt.privs == 1) {
+ lt.privs = 0;
+ }
+ lt.proceed();
+ game.removeDuskObject(lt);
+ game.addDuskObject(lt);
+ return "You have been removed from your clan.";
+ }
+ } catch (Exception e) {
+ game.log.printError("parseCommand():While " + lt.name + " was trying to dropout of their clan", e);
+ }
+ lt.proceed();
+ return null;
+ }
+
+ case "description": {
+ if (args == null) {
+ lt.description = null;
+ return "Your description has been removed.";
+ }
+ lt.description = args;
+ return "Your description has been set to:" + lt.description;
+ }
+
+ case "title": {
+ if (!lt.isPlayer()) {
+ return "Only players may have titles.";
+ }
+ if (args == null) {
+ lt.title = null;
+ return "Your title has been removed.";
+ }
+ lt.title = args;
+ if (lt.title.length() > game.titlecap) {
+ lt.title = lt.title.substring(0, game.titlecap);
+ }
+ return "Your title has been set to:" + lt.title;
+ }
+
+ case "password": {
+ if (!lt.isPlayer()) {
+ return "Only players can change their password.";
+ }
+ try {
+ lt.halt();
+ lt.chatMessage("Enter your current password.");
+ String strOldPass = lt.instream.readLine();
+ if (!strOldPass.equals(lt.password)) {
+ lt.proceed();
+ return "Sorry, that is not your password.";
+ }
+ lt.chatMessage("Enter a new password.");
+ String strNewPass = lt.instream.readLine();
+ lt.chatMessage("Repeat that password.");
+ String strNewPassRepeat = lt.instream.readLine();
+ if (strNewPass == null) {
+ lt.proceed();
+ return "Not a valid password.";
+ }
+ if (!strNewPass.equals(strNewPassRepeat)) {
+ lt.proceed();
+ return "Sorry, those passwords do not match.";
+ }
+ lt.password = strNewPass;
+ lt.proceed();
+ return "Your password has now been changed.";
+ } catch (Exception e) {
+ game.log.printError("parseCommand():While " + lt.name + " was changing their password", e);
+ }
+ lt.proceed();
+ }
+
+ case "wear": {
+ if (args == null) {
+ return "Wear what?";
+ }
+ // FIXME: this should go on livingthing, but the interaction flow is messy
+ LinkedList<Item> qStore = lt.itemList.get(args);
+ if (qStore != null) {
+ Item itmStore = (Item) qStore.element();
+ int where = -1;
+
+ switch (itmStore.intType) {
+ case (1): {
+ where = Equipment.WIELD;
+ break;
+ }
+ case (2):
+ where = itmStore.intKind + Equipment.ARMS;
+ break;
+ default:
+ return "You can't wear that";
+ }
+
+ Item old = lt.wornItems.wear(where, itmStore);
+ if (old != null) {
+ lt.itemList.addElement(old);
+ lt.onUnwear(old);
+ }
+ lt.onWear(itmStore);
+
+ lt.itemList.removeElement(itmStore.name);
+ if (lt.isPet()) {
+ lt.getMaster().updateStats();
+ }
+ if (lt.isPlayer()) {
+ lt.updateStats();
+ }
+ lt.updateEquipment();
+ lt.updateItems();
+ return null;
+ }
+ return "You don't have that";
+ }
+ case "unwear": {
+ if (args == null) {
+ return "Unwear what?";
+ }
+ lt.unWear(args);
+ return null;
+ }
+ case "rement": {
+ if (args == null) {
+ return null;
+ }
+ long lngID = Long.parseLong(args);
+ lt.removeEntity(lngID);
+ return null;
+ }
+ case "audio": {
+ if (args == null) {
+ if (lt.audioon) {
+ return "Your audio is turned on.";
+ }
+ return "Your audio is turned off.";
+ } else if (args.equalsIgnoreCase("off")) {
+ lt.audioon = false;
+ return "Your audio has been turned off.";
+ } else if (args.equalsIgnoreCase("on")) {
+ lt.audioon = true;
+ return "Your audio has been turned on.";
+ }
+ }
+ case "color": {
+ if (args == null) {
+ if (lt.coloron) {
+ return "Your color is turned on.";
+ }
+ return "Your color is turned off.";
+ } else if (args.equalsIgnoreCase("off")) {
+ lt.coloron = false;
+ return "Your color has been turned off.";
+ } else if (args.equalsIgnoreCase("on")) {
+ lt.coloron = true;
+ return "Your color has been turned on.";
+ }
+ }
+ case "highlight": {
+ if (args == null) {
+ if (lt.highlight) {
+ return "Highlighting of enemies in battle is turned on.";
+ }
+ return "Highlighting of enemies in battle is turned off.";
+ } else if (args.equalsIgnoreCase("off")) {
+ lt.highlight = false;
+ lt.clearFlags();
+ return "Highlighting of enemies in battle has been turned off.";
+ } else if (args.equalsIgnoreCase("on")) {
+ lt.highlight = true;
+ return "Highlighting of enemies in battle has been turned on.";
+ }
+ }
+ case "popup": {
+ // FIXME: TBD
+ if (args == null) {
+ if (lt.popup) {
+ return "You have popup windows turned on.";
+ }
+ return "You have popup windows turned off.";
+ } else if (args.equalsIgnoreCase("off")) {
+ lt.popup = false;
+ return "You have turned popup windows off.";
+ } else if (args.equalsIgnoreCase("on")) {
+ lt.popup = true;
+ return "You have turned popup windows on.";
+ }
+ }
+ case "nofollow": {
+ if (args == null) {
+ if (lt.noFollow) {
+ return "You are not allowed to be followed.";
+ }
+ return "You can be followed.";
+ } else if (args.equalsIgnoreCase("off")) {
+ lt.noFollow = false;
+ return "You can now be followed.";
+ } else if (args.equalsIgnoreCase("on")) {
+ lt.noFollow = true;
+ return "You can no longer be followed.";
+ }
+ }
+ case "ignore": {
+ if (args == null) {
+ return "Ignore who?";
+ }
+ LivingThing thnStore = game.getPlayer(args);
+ if (thnStore == null) {
+ return "They're not in this world.";
+ }
+ String strIgnoreName = thnStore.name.toLowerCase();
+ if (lt.name.equalsIgnoreCase(strIgnoreName)) {
+ return "Trying to ignore yourself is not a good sign.";
+ }
+ if (thnStore.privs > 2) {
+ return "You cannot ignore a god.";
+ }
+ if (!lt.ignoreList.contains(strIgnoreName)) {
+ lt.ignoreList.add(strIgnoreName);
+ } else {
+ return "You are already ignoring them.";
+ }
+ return "You are now ignoring " + strIgnoreName;
+ }
+ case "unignore": {
+ if (args == null) {
+ return "UnIgnore who?";
+ }
+ String strIgnoreName = args.toLowerCase();
+ if (strIgnoreName == "all") {
+ lt.ignoreList.clear();
+ return "You are no longer ignoring anyone.";
+ }
+ if (lt.ignoreList.contains(strIgnoreName)) {
+ lt.ignoreList.remove(strIgnoreName);
+ } else {
+ return "You are not ignoring them.";
+ }
+ return "You are no longer ignoring " + strIgnoreName;
+ }
+ case "appletimages": {
+ lt.updateAppletImages();
+ return null;
+ }
+ case "applicationimages": {
+ lt.updateApplicationImages();
+ return null;
+ }
+ case "notdead": {
+ return null;
+ }
+ case "quit":
+ case "logout": {
+ if (lt.battle == null) {
+ lt.close();
+ return null;
+ }
+ return "You cannot quit in the middle of a fight.";
+ }
+ }
+ if (!blnFoundScriptedCommand) {
+ return "huh?";
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - modernised java, clean up script commands.
+ */
+package duskz.server;
+
+import duskz.server.entity.LivingThing;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ * Condition describes a temporary or permanent effect.
+ *
+ * @author Tom Weingarten
+ */
+public class Condition {
+
+ public final String name;
+ public int duration = -1, //number of occurances till end. -1 = infinity
+ occurance = 1, //number of ticks per occurance
+ ticksPast = 0; //how many ticks since last occurance
+ public boolean display = true; //should the player be able to see the condition
+ // Script names
+ private String onStartScript = null,
+ onOccuranceScript = null,
+ onEndScript = null;
+
+ public Condition(String name) {
+ this.name = name;
+ }
+
+ public static Condition getCondition(String name) throws IOException {
+ String s;
+ Condition store = new Condition(name);
+
+ try (RandomAccessFile rafConditionDef = new RandomAccessFile("defConditions/" + name.toLowerCase(), "r")) {
+ s = rafConditionDef.readLine();
+ while (!(s == null || s.equals("."))) {
+ switch (s.toLowerCase()) {
+ case "duration":
+ store.duration = Integer.parseInt(rafConditionDef.readLine());
+ break;
+ case "occurance":
+ store.occurance = Integer.parseInt(rafConditionDef.readLine());
+ break;
+ case "onstart":
+ store.onStartScript = rafConditionDef.readLine();
+ break;
+ case "onoccurance":
+ store.onOccuranceScript = rafConditionDef.readLine();
+ break;
+ case "onend":
+ store.onEndScript = rafConditionDef.readLine();
+ break;
+ case "nodisplay":
+ store.display = false;
+ break;
+ }
+ s = rafConditionDef.readLine();
+ }
+ }
+ return store;
+ }
+
+ void runScript(DuskEngine engGame, LivingThing trigger, String script) {
+ if (script != null) {
+ try {
+ Script scrStore = new Script("scripts/" + script, engGame, false);
+ scrStore.varVariables.addVariable("trigger", trigger);
+ scrStore.varVariables.addVariable("condition", name);
+ scrStore.runScript();
+ scrStore.close();
+ } catch (Exception e) {
+ engGame.log.printError("Condition.onStart() for condition \"" + name + "\"", e);
+ }
+ }
+ }
+
+ public void onStart(DuskEngine engGame, LivingThing trigger) {
+ runScript(engGame, trigger, onStartScript);
+ }
+
+ public void onOccurance(DuskEngine engGame, LivingThing trigger) {
+ runScript(engGame, trigger, onOccuranceScript);
+ }
+
+ public void onEnd(DuskEngine engGame, LivingThing trigger) {
+ runScript(engGame, trigger, onEndScript);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server;
+
+import java.util.Properties;
+import java.io.FileInputStream;
+
+class Config extends Properties {
+
+ DuskEngine engGame;
+
+ public Config(DuskEngine inGame, String strFileName) {
+ engGame = inGame;
+ try {
+ load(new FileInputStream(strFileName));
+ } catch (Exception e) {
+ engGame.log.printError("Config::Config(String) - Error loading preferences.", e);
+ }
+ }
+
+ public String getString(String strKey, String strDefault) {
+ String strReturn = getProperty(strKey, strDefault);
+ engGame.log.printMessage(Log.VERBOSE, strKey + " = " + strReturn);
+ return strReturn;
+ }
+
+ public int getInt(String strKey, int intDefault) {
+ int intReturn = Integer.parseInt(getProperty(strKey, String.valueOf(intDefault)));
+ engGame.log.printMessage(Log.VERBOSE, strKey + " = " + intReturn);
+ return intReturn;
+ }
+
+ public boolean getBoolean(String strKey, boolean blnDefault) {
+ boolean blnReturn = (Boolean.valueOf(getProperty(strKey, String.valueOf(blnDefault))).booleanValue());
+ engGame.log.printMessage(Log.VERBOSE, strKey + " = " + blnReturn);
+ return blnReturn;
+ }
+
+ public long getLong(String strKey, long lngDefault) {
+ long lngReturn = Long.parseLong(getProperty(strKey, String.valueOf(lngDefault)));
+ engGame.log.printMessage(Log.VERBOSE, strKey + " = " + lngReturn);
+ return lngReturn;
+ }
+
+ public double getDouble(String strKey, double dblDefault) {
+ double dblReturn = Double.parseDouble(getProperty(strKey, String.valueOf(dblDefault)));
+ engGame.log.printMessage(Log.VERBOSE, strKey + " = " + dblReturn);
+ return dblReturn;
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server;
+
+/**
+ * This class defines all constants used throughout the code system.
+ *
+ * @Author Lee Templeton (Lone Wolf)
+ */
+//TODO: Move all commonly used variables to here
+public interface Constants {
+ // DUSKENGINE Section
+
+ static final int MIN = 0;
+ static final int MAX = 1;
+ // DUSKOBJECT Section
+ static final int NUMBER = 0;
+ static final int STRING = 1;
+ static final int LIVING_THING = 2;
+ static final int ITEM = 3;
+ // ATTRIBUTE Section
+ static final int MAIN = 0;
+ static final int SECONDARY = 1;
+ static final int BONUS = 2;
+ static final int ALL = 100;
+ // ITEM Section
+ static final int ORDINARY_ITEM = 0;
+ static final int WEAPON = 1;
+ static final int ARMOR = 2;
+ static final int FOOD = 3;
+ static final int DRINK = 4;
+ static final int RANGED = 5;
+ static final int CONTAINER = 6;
+ // CAP Section
+ static final int STAT_CAP = 100;
+ static final int SKILL_CAP = 100;
+ static final int MAX_CAP = 200;
+ // Strings
+ static final String CONFIG_FILE_NAME = "prefs";
+ static final String CONFIG_FILE_DIR = "conf/";
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - general cleanup, modernisation, refactoring,
+ * abstracting, fixing synchronisation issues.
+ */
+package duskz.server;
+
+import duskz.protocol.MessageType;
+import duskz.server.entity.TileMap;
+import duskz.server.entity.Mob;
+import duskz.server.entity.Merchant;
+import duskz.server.entity.Sign;
+import duskz.server.entity.Item;
+import duskz.server.entity.Prop;
+import duskz.server.entity.DuskObject;
+import duskz.server.entity.PlayerMerchant;
+import duskz.server.entity.LivingThing;
+import duskz.protocol.ServerMessage;
+import duskz.protocol.TransactionItem;
+import java.io.*;
+import java.io.PrintStream;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+/**
+ * DuskEngine is the center of the Dusk game.
+ *
+ * @author Tom Weingarten
+ */
+public class DuskEngine implements Runnable {
+ //Logger
+
+ public Log log;
+ //Prefs:
+ public int port = 7400,
+ trackerport = 7401,
+ maxconnections = 0,
+ petcost = 100,
+ merchantimage,
+ signimage,
+ battlesound = -1,
+ mobrespawnspeed,
+ viewrange = 5,
+ oldviewrange = 0,
+ mapsize = 11,
+ titlecap = 0,
+ noChannelMax = 600, // defalut 600=10 minutes
+ namecap = 20, //default 20
+ messagecap = 120, //default 120
+ changeRaceCpLimit = 100, //default 100cp
+ logLevel = Log.ERROR,
+ traincost = 100,
+ expgainmod = 10;
+ double gplosemod = 1D / 16D, //default 1/16
+ explosemod = 1D / 16D,
+ gpfleemod = 1D / 64D, //default 1/64
+ expfleemod = 1D / 64D;
+ public long lngMobTicks = 1000, //default 1000 milliseconds(1 second) per tick
+ lngPlayerTicks = 250, //default 250 milliseconds(1/4 second) per tick
+ floodLimit = 1000; //default 1000 milliseconds(1 second) btw messages
+ public String trackername = "Just Some World.",
+ site = "none",
+ strRCAddress,
+ strRCName,
+ strLogFile = null,
+ strMusicAddress;
+ public boolean blnMusic = false,
+ blnLineOfSight = false,
+ blnAI = false,
+ blnIPF = false,
+ tracker = true,
+ blnSavingGame = false,
+ blnShuttingDown = false;
+ // FIXME: Not public
+ public Script scrCanSeeLivingThing = null,
+ scrCanMoveThroughLivingThing = null,
+ scrCanAttack = null,
+ scrOnStart = null,
+ scrOnDeath = null,
+ scrOnLogOut = null;
+ //End Prefs
+ public final static String version = "2.6.2.W42";
+ public final Date datStart = new Date(System.currentTimeMillis());
+ //public int MapRows,
+ // MapColumns;
+ //public short shrMap[][];
+ //protected short shrMapOwnerPrivs[][];
+ //protected int intMapOwnerID[][];
+ //protected Config IDtoName;
+ public TileMap map;
+ final public List<Battle> battleList = new ArrayList<>();
+ // Indices of various Entities
+ final public HashSet<Merchant> merchantList = new HashSet<>();
+ /**
+ * List of mobs in game.
+ * access must be synchronised.
+ */
+ final public List<Mob> mobList = new ArrayList<>();
+ // TODO: although this is maintained, nobody access it
+ final public List<Item> itemList = new ArrayList<>();
+ final public List<Sign> signList = new ArrayList<>();
+ final public List<Prop> propList = new ArrayList<>();
+ final public List<LivingThing> petList = new ArrayList<>();
+ // tile actions, keyed by tile id
+ final public HashMap<Integer, Script> tileCanSee = new HashMap<>();
+ final public HashMap<Integer, Script> tileCanMove = new HashMap<>();
+ final public HashMap<Integer, Script> tileAction = new HashMap<>();
+ //
+ final public HashMap<String, Faction> factionMap = new HashMap<>();
+ final public HashMap<String, SpellGroup> spellGroupList = new HashMap<>();
+ /**
+ * Automatic temporary bans
+ */
+ final private HashMap<String, Long> bannedIPMap = new HashMap<>();
+ final public HashSet<LivingThing> checkConditionList = new HashSet<>();
+ public final HashMap<String, LivingThing> playersByName = new HashMap<>();
+ VariableSet varVariables;
+ public VariableSet varIP;
+ private long nextid = 0;
+ boolean blnVariableListChanged = false,
+ blnMapHasChanged = false,
+ blnMobListChanged = false,
+ blnSignListChanged = false,
+ blnMerchantListChanged = false,
+ blnPropListChanged = false;
+
+ public DuskEngine() {
+ RandomAccessFile rafFile = null;
+ varVariables = new VariableSet();
+ varIP = new VariableSet();
+ log = new Log(System.out);
+
+ try {
+ int x = 0,
+ y = 0;
+ String strStore;
+
+ loadPrefs();
+
+ // Load Map
+ File newmap = new File("shortmapx");
+ if (newmap.exists()) {
+ log.printMessage(Log.INFO, "Loading Map...");
+ map = TileMap.loadMapX(newmap);
+ log.printMessage(Log.VERBOSE, map.getCols() + "/" + map.getRows());
+ } else {
+ newmap = new File("shortmap");
+ if (newmap.exists()) {
+ log.printMessage(Log.INFO, "Loading Map...");
+ map = TileMap.loadMap(newmap, TileMap.FORMAT_SHORT);
+ log.printMessage(Log.VERBOSE, map.getCols() + "/" + map.getRows());
+ } else {
+ log.printMessage(Log.INFO, "Converting old map to new short format...");
+ map = TileMap.loadMap(newmap, TileMap.FORMAT_BYTE);
+ log.printMessage(Log.VERBOSE, map.getCols() + "/" + map.getRows());
+ }
+ }
+
+ log.printMessage(Log.INFO, "Map Loaded...");
+
+ // Loading Map tile priviledges
+ /*
+ File mapprivs = new File("shortmap.privs");
+ if (mapprivs.exists()) {
+ rafFile = new RandomAccessFile("shortmap.privs", "r");
+ log.printMessage(Log.INFO, "Loading Map Tile Privs...");
+ int PrivsColumns = rafFile.readInt();
+ int PrivsRows = rafFile.readInt();
+ if (PrivsColumns != MapColumns || PrivsRows != MapRows) {
+ log.printMessage(Log.ERROR, "Map privs array size (" + PrivsColumns + "/" + PrivsRows + ") does not match map size (" + MapColumns + "/" + MapRows + ")");
+ }
+ log.printMessage(Log.ALWAYS, PrivsColumns + "/" + PrivsRows);
+ shrMapOwnerPrivs = new short[PrivsColumns][PrivsRows];
+ for (x = 0; x < PrivsColumns; x++) {
+ for (y = 0; y < PrivsRows; y++) {
+ shrMapOwnerPrivs[x][y] = rafFile.readShort();
+ }
+ }
+ rafFile.close();
+ }
+
+ // Loading Map tile ownership
+ File mapowners = new File("shortmap.owner");
+ File ownerlist = new File("tile_owner_list");
+ if (mapowners.exists() && ownerlist.exists()) {
+ IDtoName = new Config(this, "tile_owner_list");
+ rafFile = new RandomAccessFile("shortmap.owner", "r");
+ log.printMessage(Log.INFO, "Loading Map Tile Ownership...");
+ int OwnColumns = rafFile.readInt();
+ int OwnRows = rafFile.readInt();
+ if (OwnColumns != MapColumns || OwnRows != MapRows) {
+ log.printMessage(Log.ERROR, "Map ownership array size (" + OwnColumns + "/" + OwnRows + ") does not match map size (" + MapColumns + "/" + MapRows + ")");
+ }
+ log.printMessage(Log.ALWAYS, OwnColumns + "/" + OwnRows);
+ intMapOwnerID = new int[OwnColumns][OwnRows];
+ for (x = 0; x < OwnColumns; x++) {
+ for (y = 0; y < OwnRows; y++) {
+ intMapOwnerID[x][y] = rafFile.readInt();
+ }
+ }
+ rafFile.close();
+ }*/
+
+ // Load Merchants
+ try {
+ rafFile = new RandomAccessFile("merchants", "r");
+ Merchant mrcStore;
+ log.printMessage(Log.INFO, "Loading Merchants...");
+ strStore = rafFile.readLine();
+ while (!(strStore == null || strStore.equals(""))) {
+ mrcStore = new Merchant(this);
+ mrcStore.x = Integer.parseInt(strStore);
+ mrcStore.y = Integer.parseInt(rafFile.readLine());
+ log.printMessage(Log.VERBOSE, "Merchant(" + mrcStore.x + "," + mrcStore.y + ")");
+ strStore = rafFile.readLine();
+ while (strStore != null && !strStore.equals("") && !strStore.equalsIgnoreCase("end")) {
+ log.printMessage(Log.DEBUG, "\t" + strStore);
+ mrcStore.items.add(strStore);
+ strStore = rafFile.readLine();
+ }
+ if (!map.inside(mrcStore.x, mrcStore.y)) {
+ log.printMessage(Log.VERBOSE, "Previous merchant is off of the map, ignoring");
+ blnMerchantListChanged = true;
+ } else {
+ //vctMerchants.add(mrcStore);
+ addDuskObject(mrcStore);
+ }
+ strStore = rafFile.readLine();
+ }
+ } catch (Exception e) {
+ log.printError("DuskEngine():While loading merchants", e);
+ }
+ rafFile.close();
+
+ // Load Mobs
+ LivingThing thnStore;
+ rafFile = new RandomAccessFile("mobs", "r");
+ log.printMessage(Log.INFO, "Loading Mobs...");
+ strStore = rafFile.readLine();
+ while (strStore != null) {
+ if (strStore.equals("")) {
+ break;
+ }
+ if (strStore.equals("mob2.3")) {
+ strStore = rafFile.readLine();
+ log.printMessage(Log.VERBOSE, strStore);
+ try {
+ thnStore = new Mob(strStore,
+ Integer.parseInt(rafFile.readLine()),
+ Integer.parseInt(rafFile.readLine()),
+ this);
+ if (!map.inside(thnStore.x, thnStore.y)) {
+ log.printMessage(Log.VERBOSE, "Previous mob is off of the map, ignoring");
+ blnMobListChanged = true;
+ } else {
+ //vctMobs.addElement(thnStore);
+ addDuskObject(thnStore);
+ }
+ } catch (Exception e) {
+ log.printError("DuskEngine():While loading mobs", e);
+ }
+ } else {
+ log.printMessage(Log.VERBOSE, strStore);
+ try {
+ thnStore = new Mob(strStore,
+ Integer.parseInt(rafFile.readLine()),
+ Integer.parseInt(rafFile.readLine()),
+ Integer.parseInt(rafFile.readLine()),
+ this);
+ if (!map.inside(thnStore.x, thnStore.y)) {
+ log.printMessage(Log.VERBOSE, "Previous mob is off of the map, ignoring");
+ blnMobListChanged = true;
+ } else {
+ //vctMobs.addElement(thnStore);
+ addDuskObject(thnStore);
+ }
+ } catch (Exception e) {
+ log.printError("DuskEngine():While loading mobs", e);
+ }
+ }
+ strStore = rafFile.readLine();
+ }
+ rafFile.close();
+
+ // Load signs
+ Sign sgnStore;
+ rafFile = new RandomAccessFile("signs", "r");
+ log.printMessage(Log.INFO, "Loading Signs...");
+ strStore = rafFile.readLine();
+ while (!(strStore == null || strStore.equals(""))) {
+ log.printMessage(Log.VERBOSE, strStore);
+ sgnStore = new Sign(this, "sign", strStore, Integer.parseInt(rafFile.readLine()), Integer.parseInt(rafFile.readLine()), getID());
+ if (!map.inside(sgnStore.x, sgnStore.y)) {
+ log.printMessage(Log.VERBOSE, "Previous sign is off of the map, ignoring");
+ blnSignListChanged = true;
+ } else {
+ //vctSigns.add(sgnStore);
+ addDuskObject(sgnStore);
+ }
+ strStore = rafFile.readLine();
+ }
+ rafFile.close();
+
+ // Load props
+ Prop prpStore;
+ rafFile = new RandomAccessFile("props", "r");
+ log.printMessage(Log.INFO, "Loading Props...");
+ strStore = rafFile.readLine();
+ while (!(strStore == null || strStore.equals(""))) {
+ log.printMessage(Log.VERBOSE, strStore);
+ prpStore = getProp(strStore);
+ if (prpStore != null) {
+ prpStore.x = Integer.parseInt(rafFile.readLine());
+ prpStore.y = Integer.parseInt(rafFile.readLine());
+ if (!map.inside(prpStore.x, prpStore.y)) {
+ log.printMessage(Log.VERBOSE, "Previous prop is off of the map, ignoring");
+ blnPropListChanged = true;
+ } else {
+ //vctProps.addElement(prpStore);
+ addDuskObject(prpStore);
+ }
+ }
+ strStore = rafFile.readLine();
+ }
+ rafFile.close();
+
+ // Load global variables
+ String strVarName;
+ int intType;
+ String strObject;
+ double dblObject;
+ rafFile = new RandomAccessFile("globals", "r");
+ log.printMessage(Log.INFO, "Loading Global Variables...");
+ strVarName = rafFile.readLine();
+ while (!(strVarName == null || strVarName.equals(""))) {
+ intType = Integer.parseInt(rafFile.readLine());
+ switch (intType) {
+ case 0: {
+ dblObject = (double) Double.parseDouble(rafFile.readLine());
+ varVariables.addVariable(strVarName, dblObject);
+ log.printMessage(Log.VERBOSE, strVarName + " = " + dblObject);
+ break;
+ }
+ case 1: {
+ strObject = rafFile.readLine();
+ varVariables.addVariable(strVarName, strObject);
+ log.printMessage(Log.VERBOSE, strVarName + " = '" + strObject + "'");
+ break;
+ }
+ }
+ strVarName = rafFile.readLine();
+ }
+ rafFile.close();
+
+ //Start onBoot script
+ try {
+ Script scrOnBoot = new Script("conf/onBoot", this, true);
+ scrOnBoot.runScript();
+ scrOnBoot.close();
+ log.printMessage(Log.INFO, "Ran onBoot script.");
+ } catch (Exception e) {
+ log.printError("DuskEngine():Failed to run onBoot script, maybe it doesn't exist? (Not a fatal error)", e);
+ log.printMessage(Log.ALWAYS, "To create an onBoot script, type \"view conf onBoot\" in game as a high or master god.");
+ }
+ } catch (Exception e) {
+ log.printError("DuskEngine()", e);
+ }
+ }
+
+ public boolean isGoodIP(String strIP) {
+ RandomAccessFile rafFile = null;
+ try {
+ // Why isn't this cached?
+ String strBlockedIP;
+ String key = strIP.toLowerCase();
+ rafFile = new RandomAccessFile("conf/blockedIP", "r");
+ strBlockedIP = rafFile.readLine();
+ while (strBlockedIP != null) {
+ if (key.indexOf(strBlockedIP) != -1) {
+ rafFile.close();
+ return false;
+ }
+ strBlockedIP = rafFile.readLine();
+ }
+ rafFile.close();
+
+ return !isBanned(key);
+ } catch (Exception e) {
+ log.printError("isGoodIP():Checking for bad IP address", e);
+ return false;
+ }
+ }
+
+ public boolean isGoodName(String strName) {
+ if (strName == null) {
+ return false;
+ }
+ if (strName.equals("")
+ || strName.length() > namecap
+ || strName.toLowerCase().equals("god")
+ || strName.toLowerCase().equals("default")) {
+ return false;
+ }
+
+ String strValid = "0123456789][_'#";
+ char[] letters = strName.toCharArray();
+ char[] validChars = strValid.toCharArray();
+ boolean blnValid = true;
+
+ for (int n = 0; n < letters.length; n++) {
+ if (!Character.isLetter(letters[n])) {
+ blnValid = false;
+ for (int i = 0; i < validChars.length; i++) {
+ if (letters[n] == validChars[i]) {
+ blnValid = true;
+ }
+ }
+ }
+ }
+ if (!blnValid) {
+ return false;
+ }
+
+ RandomAccessFile rafFile = null;
+ try {
+ String strDirtyWord;
+ String strLowerCaseName = strName.toLowerCase();
+ rafFile = new RandomAccessFile("conf/dirtyWordFile", "r");
+ strDirtyWord = rafFile.readLine();
+ while (strDirtyWord != null) {
+ if (strLowerCaseName.indexOf(strDirtyWord) != -1) {
+ rafFile.close();
+ return false;
+ }
+ strDirtyWord = rafFile.readLine();
+ }
+ rafFile.close();
+ } catch (Exception e) {
+ log.printError("isGoodName():" + strName + " had an error checking for bad name", e);
+ return false;
+ }
+ return true;
+ }
+
+ synchronized void loadPrefs() {
+ Config settings = new Config(this, "conf/prefs");
+ //Load Prefs
+ strLogFile = settings.getString("LogFileName", strLogFile);
+ if (strLogFile != null) {
+ try {
+ log = new Log(new PrintStream(new FileOutputStream(strLogFile, true), true));
+ } catch (Exception e) {
+ log = new Log(System.out);
+ log.printError("loadPrefs():Opening log file \"" + strLogFile + "\"", e);
+ }
+ } else {
+ log = new Log(System.out);
+ }
+ log.printMessage(Log.INFO, "Loading Preferences...");
+
+ logLevel = settings.getInt("LoggingLevel", logLevel);
+ log.setLogLevel(logLevel);
+
+ port = settings.getInt("Port", port);
+ tracker = settings.getBoolean("Tracker", tracker);
+ trackerport = settings.getInt("TrackerPort", trackerport);
+ trackername = settings.getString("TrackerName", trackername);
+ site = settings.getString("TrackerSite", site);
+ strRCAddress = settings.getString("RCAddress", strRCAddress);
+ strRCName = settings.getString("RCName", strRCName);
+ maxconnections = settings.getInt("MaxConnections", maxconnections);
+ blnMusic = settings.getBoolean("Music", blnMusic);
+ blnAI = settings.getBoolean("Ai", blnAI);
+ blnLineOfSight = settings.getBoolean("LineOfSight", blnLineOfSight);
+ blnIPF = settings.getBoolean("UniqueIPFilter", blnIPF);
+ changeRaceCpLimit = settings.getInt("ChangeRaceCPLimit", changeRaceCpLimit);
+ petcost = settings.getInt("PetCost", petcost);
+ messagecap = settings.getInt("MessageCap", messagecap);
+ namecap = settings.getInt("NameCap", namecap);
+ titlecap = settings.getInt("TitleCap", titlecap);
+ noChannelMax = settings.getInt("NoChannelMax", noChannelMax);
+ merchantimage = settings.getInt("MerchantImage", merchantimage);
+ signimage = settings.getInt("SignImage", signimage);
+ battlesound = settings.getInt("BattleSound", battlesound);
+ mobrespawnspeed = -1 * settings.getInt("MobReSpawnSpeed", mobrespawnspeed);
+ traincost = settings.getInt("TrainCost", traincost);
+ expgainmod = settings.getInt("ExpGainMod", expgainmod);
+ gplosemod = settings.getDouble("GpLoseMod", gplosemod);
+ explosemod = settings.getDouble("ExpLoseMod", explosemod);
+ gpfleemod = settings.getDouble("GpFleeMod", gpfleemod);
+ expfleemod = settings.getDouble("ExpFleeMod", expfleemod);
+ viewrange = settings.getInt("ViewRange", viewrange);
+ lngMobTicks = settings.getLong("MobTicks", lngMobTicks);
+ lngPlayerTicks = settings.getLong("PlayerTicks", lngPlayerTicks);
+ if (viewrange != oldviewrange) {
+ oldviewrange = viewrange;
+ mapsize = 1 + (2 * viewrange);
+ for (LivingThing thnStore : playersByName.values()) {
+ thnStore.resizeMap();
+ }
+ }
+ //Load Triggered Scripts
+
+ // FIXME: all this 'synchronized' stuff is busted to shit, you can't lock on something
+ // that might be null or will be replaced by a new object.
+
+ try {
+ if (scrCanSeeLivingThing != null) {
+ synchronized (scrCanSeeLivingThing) {
+ scrCanSeeLivingThing.close();
+ scrCanSeeLivingThing = new Script("conf/canSeeLivingThing", this, true);
+ }
+ } else {
+ scrCanSeeLivingThing = new Script("conf/canSeeLivingThing", this, true);
+ }
+ } catch (Exception e) {
+ scrCanSeeLivingThing = null;
+ }
+ try {
+ if (scrCanMoveThroughLivingThing != null) {
+ synchronized (scrCanMoveThroughLivingThing) {
+ scrCanMoveThroughLivingThing.close();
+ scrCanMoveThroughLivingThing = new Script("conf/canMoveThroughLivingThing", this, true);
+ }
+ } else {
+ scrCanMoveThroughLivingThing = new Script("conf/canMoveThroughLivingThing", this, true);
+ }
+ } catch (Exception e) {
+ scrCanMoveThroughLivingThing = null;
+ }
+ try {
+ if (scrCanAttack != null) {
+ synchronized (scrCanAttack) {
+ scrCanAttack.close();
+ scrCanAttack = new Script("conf/canAttack", this, true);
+ }
+ } else {
+ scrCanAttack = new Script("conf/canAttack", this, true);
+ }
+ } catch (Exception e) {
+ scrCanAttack = null;
+ }
+ try {
+ if (scrOnStart != null) {
+ synchronized (scrOnStart) {
+ scrOnStart.close();
+ scrOnStart = new Script("conf/onStart", this, true);
+ }
+ } else {
+ scrOnStart = new Script("conf/onStart", this, true);
+ }
+ } catch (Exception e) {
+ scrOnStart = null;
+ }
+ try {
+ if (scrOnDeath != null) {
+ synchronized (scrOnDeath) {
+ scrOnDeath.close();
+ scrOnDeath = new Script("conf/onDeath", this, true);
+ }
+ } else {
+ scrOnDeath = new Script("conf/onDeath", this, true);
+ }
+ } catch (Exception e) {
+ scrOnDeath = null;
+ }
+ try {
+ if (scrOnLogOut != null) {
+ synchronized (scrOnLogOut) {
+ scrOnLogOut.close();
+ scrOnLogOut = new Script("conf/onLogOut", this, true);
+ }
+ } else {
+ scrOnLogOut = new Script("conf/onLogOut", this, true);
+ }
+ } catch (Exception e) {
+ scrOnLogOut = null;
+ }
+
+ File f = new File("tileScriptMap");
+ if (f.exists()) {
+ // Load tile scripts throuhg indirection
+ try {
+ Properties props = new Properties();
+ try (FileInputStream fis = new FileInputStream(f)) {
+ props.load(fis);
+
+ for (Entry e : props.entrySet()) {
+ String key = (String) e.getKey();
+ String val = (String) e.getValue();
+
+ HashMap<Integer, Script> target = null;
+ String path = null;
+ String id = null;
+ if (key.startsWith("move.")) {
+ target = tileCanMove;
+ path = "defTileScripts/";
+ id = key.substring(5);
+ } else if (key.startsWith("see.")) {
+ target = tileCanSee;
+ path = "defTileActions/";
+ id = key.substring(4);
+ } else if (key.startsWith("action.")) {
+ target = tileAction;
+ path = "defTileSeeScripts/";
+ id = key.substring(7);
+ }
+ if (target != null) {
+ try {
+ target.put(Integer.valueOf(id), new Script(path + val, this, true));
+ } catch (Exception x) {
+ }
+ }
+ }
+ }
+ } catch (IOException x) {
+ }
+ } else {
+ // Load Tile Scripts
+ loadTileScripts(tileCanMove, "defTileScripts/");
+ loadTileScripts(tileAction, "defTileActions/");
+ loadTileScripts(tileCanSee, "defTileSeeScripts/");
+ }
+ }
+
+ void loadTileScripts(HashMap<Integer, Script> scripts, String path) {
+ try {
+ int i;
+ for (Script s : scripts.values()) {
+ s.close();
+ }
+ scripts.clear();
+ // FIXME: just try to load known tile sizes, we know how many tiles we have
+ for (i = 0; true; i++) {
+ try {
+ scripts.put(i, new Script(path + i, this, true));
+ } catch (Exception e) {
+ break;
+ }
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ public synchronized long getID() {
+ nextid++;
+ return nextid;
+ }
+
+ public void chatMessage(String msg, String from) {
+ from = from.toLowerCase();
+ log.printMessage(Log.ALWAYS, msg);
+ for (LivingThing lt : playersByName.values()) {
+ if (!lt.ignoreList.contains(from)) {
+ lt.chatMessage(msg);
+ }
+ }
+ }
+
+ public void chatMessage(String inMessage, int locx, int locy, String strFrom) {
+ strFrom = strFrom.toLowerCase();
+ LivingThing thnStore;
+ log.printMessage(Log.ALWAYS, inMessage);
+
+ for (TileMap.MapData md : map.range(locx, locy, viewrange)) {
+ for (DuskObject o : md.entities) {
+ if (o.isLivingThing()) {
+ thnStore = (LivingThing) o;
+ if (thnStore.isPlayer()
+ && !thnStore.ignoreList.contains(strFrom)) {
+ thnStore.chatMessage(inMessage);
+ }
+ }
+ }
+ }
+ }
+
+ public void chatMessage(String msg, String clan, String from) {
+ from = from.toLowerCase();
+ log.printMessage(Log.ALWAYS, msg);
+ for (LivingThing lt : playersByName.values()) {
+ if (lt.clan.equals(clan)
+ && !lt.ignoreList.contains(from)) {
+ lt.chatMessage(msg);
+ }
+ }
+ }
+
+ public void refreshEntities(LivingThing refresh) {
+ LinkedList<DuskObject> newEntities = new LinkedList<>();
+
+ for (TileMap.MapData md : map.range(refresh.x, refresh.y, viewrange)) {
+ if (!md.entities.isEmpty()
+ && canSeeTo(refresh, md.x, md.y)) {
+ for (DuskObject o : md.entities) {
+ newEntities.add(o);
+ //old = thnRefresh.removeEntity(objStore.ID);
+ //for (i4 = 0; i4 < thnRefresh.nearEntities.size(); i4++) {
+ // objStore2 = (DuskObject) thnRefresh.nearEntities.elementAt(i4);
+ // if (objStore2 == objStore) {
+ // thnRefresh.nearEntities.removeElementAt(i4);
+ // i4 = -1;
+ // break;
+ // }
+ //}
+ if (o.isPlayerMerchant()) {
+ PlayerMerchant shop = (PlayerMerchant) o;
+ if (refresh.x == shop.x && refresh.y == shop.y) {
+ //strResult = (char) 17 + "";
+ StringBuilder sb = new StringBuilder();
+ for (String name : shop.vctItems.keySet()) {
+ LinkedList<Item> vctStore = shop.vctItems.get(name);
+ Item item = (Item) vctStore.element();
+ int intCost = (item.intCost * 3) / 4;
+
+ if (refresh.name.equalsIgnoreCase(shop.strOwner)) {
+ intCost = 0;
+ }
+ sb.append(intCost + "gp)" + name + "\n");
+ }
+ sb.append(".\n");
+ refresh.send(MessageType.UpdateMerchant, sb.toString());
+ refresh.updateSell();
+ }
+ }
+ if (o.isMerchant()) {
+ Merchant merchant = (Merchant) o;
+ if (refresh.x == merchant.x && refresh.y == merchant.y) {
+ if (true) {
+ StringBuilder sb = new StringBuilder();
+ //strResult = (char) 17 + "";
+ if (refresh.getFollowing() != null && refresh.getFollowing().isPet()) {
+ for (int i5 = 0; i5 < merchant.items.size(); i5++) {
+ String itemname = (String) merchant.items.get(i5);
+ Item item = getItem(itemname);
+ if (item != null) {
+ sb.append(item.intCost).append("gp)").append(itemname).append("\n");
+ } else if (itemname.equals("pet")) {
+ sb.append(petcost).append("gp)").append(itemname).append("\n");
+ } else {
+ sb.append(traincost).append("exp)").append(itemname).append("\n");
+ sb.append(traincost).append("exp)").append(refresh.getFollowing().name).append(":").append(itemname).append("\n");
+ }
+ }
+ } else {
+ for (int i5 = 0; i5 < merchant.items.size(); i5++) {
+ String itemname = (String) merchant.items.get(i5);
+ Item item = getItem(itemname);
+ if (item != null) {
+ sb.append(item.intCost).append("gp)").append(itemname).append("\n");
+ } else if (itemname.equals("pet")) {
+ sb.append(petcost).append("gp)").append(itemname).append("\n");
+ } else {
+ sb.append(traincost).append("exp)").append(itemname).append("\n");
+ }
+ }
+ }
+ sb.append(".\n");
+ refresh.send(MessageType.UpdateMerchant, sb.toString());
+ refresh.updateSell();
+ } else {
+ HashMap<String, TransactionItem> items = new HashMap<>();
+ for (String itemname : merchant.items) {
+ TransactionItem titem = items.get(itemname);
+ if (titem == null) {
+ Item item = getItem(itemname);
+ if (item != null) {
+ titem = new TransactionItem(itemname, 1, item.intCost, "gp");
+ } else if (itemname.equals("pet")) {
+ titem = new TransactionItem(itemname, 1, petcost, "gp");
+ } else {
+ if (refresh.getFollowing() != null && refresh.getFollowing().isPet()) {
+ titem = new TransactionItem(refresh.getFollowing().name + ":" + itemname, 1, traincost, "exp");
+ items.put(titem.name, titem);
+ }
+ titem = new TransactionItem(itemname, 1, traincost, "exp");
+ //sb.append(traincost).append("exp)").append(itemname).append("\n");
+ //sb.append(traincost).append("exp)").append(refresh.getFollowing().name).append(":").append(itemname).append("\n");
+ }
+ items.put(titem.name, titem);
+ } else {
+ titem.count++;
+ }
+ }
+ refresh.send(new ServerMessage.ItemsMessage(MessageType.UpdateMerchant, new ArrayList<>(items.values())));
+ refresh.updateSell();
+ }
+ }
+ //if (old == null) { //i4 != -1
+ // if (!objStore.isLivingThing()
+ // || canSeeLivingThing(thnRefresh, (LivingThing) objStore)) {
+ // thnRefresh.send(MessageType.AddEntity, objStore.toEntity());
+ // }
+ //}
+ }
+ }
+ }
+ }
+ // Remove those left
+ //for (DuskObject o: thnRefresh.nearEntities) {
+ // thnRefresh.send(MessageType.RemoveEntity, o.ID + "\n");
+ //}
+ //thnRefresh.nearEntities = vctNewEntities;
+ refresh.setEntities(newEntities);
+ }
+
+ public void addEntity(DuskObject add) {
+ for (TileMap.MapData md : map.range(add.x, add.y, viewrange)) {
+ for (DuskObject o : md.entities) {
+ if (o.isLivingThing()) {
+ LivingThing lt = (LivingThing) o;
+ if (lt.isPlayer()) {
+ // FIXME: see if this can be merged with updateEntity() above
+
+ if (canSeeTo(lt, add.x, add.y)) {
+ if ((!add.isLivingThing()
+ || canSeeLivingThing(lt, (LivingThing) add))) {
+ lt.addEntity(add);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void cleanup() {
+ log.printMessage(Log.INFO, "Starting cleanup.");
+ for (TileMap.MapData md : map) {
+ for (DuskObject o : md.entities) {
+ if (o.isLivingThing()) {
+ LivingThing lt = (LivingThing) o;
+ if (lt.isPlayer()) {
+ if (!playersByName.containsKey(lt.name)) {
+ log.printMessage(Log.INFO, "**found defunct player at " + md.x + "," + md.y + " during cleanup.");
+ removeDuskObject(lt);
+ lt.battle = null;
+ lt.isStopped = true;
+ }
+ }
+ if (lt.isPet()) {
+ if (!petList.contains(lt)) {
+ log.printMessage(Log.INFO, "**found defunct pet at " + md.x + "," + md.y + " during cleanup.");
+ removeDuskObject(lt);
+ }
+ }
+ }
+ }
+ }
+ log.printMessage(Log.INFO, "Finished cleanup.");
+ }
+
+ void notifyRemoved(DuskObject remove) {
+ for (TileMap.MapData md : map.range(remove.x, remove.y, viewrange)) {
+ for (DuskObject o : md.entities) {
+ if (o.isLivingThing()) {
+ LivingThing lt = (LivingThing) o;
+
+ if (lt.isPlayer()) {
+ if (canSeeTo(lt, remove.x, remove.y)) {
+ lt.removeEntity(remove.ID);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void newBattle(LivingThing pla1, LivingThing pla2) {
+ if (pla2 == null) {
+ return;
+ }
+ if (pla1.isPet()) {
+ pla1.chatMessage("Pets cannot lead battles.");
+ return;
+ }
+ if (pla1.battle != null) {
+ pla1.chatMessage("You're already fighting!");
+ return;
+ }
+ if (pla1 == pla2) {
+ pla1.chatMessage("You can't fight yourself!");
+ return;
+ }
+ if (pla2.isPet()) {
+ pla1.chatMessage("You can't attack pets.");
+ return;
+ }
+// if (Math.abs(pla1.intLocX - pla2.intLocX) + Math.abs(pla1.intLocY - pla2.intLocY) > 1)
+ if (Math.abs(pla1.x - pla2.x) + Math.abs(pla1.y - pla2.y) > pla1.getRangeWithBonus()) {
+ System.out.println("mob range = " + Math.abs(pla1.x - pla2.x) + Math.abs(pla1.y - pla2.y));
+ System.out.println("player range = " + pla1.getRangeWithBonus());
+ pla1.chatMessage("They're too far away.");
+ return;
+ }
+ if (scrCanAttack != null) {
+ synchronized (scrCanAttack) {
+ scrCanAttack.varVariables.clearVariables();
+ scrCanAttack.varVariables.addVariable("attacking", pla1);
+ scrCanAttack.varVariables.addVariable("attacked", pla2);
+ if (!scrCanAttack.rewindAndParseScript()) {
+ pla1.chatMessage("You can't attack them.");
+ return;
+ }
+ }
+ }
+ // Check if the attacked is following the attacker
+ LivingThing thnStore = pla2;
+ while (thnStore != null) {
+ if (pla1 == thnStore) {
+ pla1.chatMessage("You can't attack a member of your group.");
+ return;
+ }
+ if (thnStore.isPlayer() && !pla1.isMob()) {
+ if (thnStore.clan == null || thnStore.clan.equalsIgnoreCase("none")) {
+ pla1.chatMessage("You can't fight them.");
+ return;
+ }
+ }
+ thnStore = thnStore.getMaster();
+ }
+ // Check if the attacker is following the attacked
+ thnStore = pla2;
+ while (thnStore != null) {
+ if (pla1 == thnStore) {
+ pla1.chatMessage("You can't attack a member of your group.");
+ return;
+ }
+ if (thnStore.isPlayer() && !pla1.isMob()) {
+ if (thnStore.clan == null || thnStore.clan.equalsIgnoreCase("none")) {
+ pla1.chatMessage("You can't fight them.");
+ return;
+ }
+ }
+ thnStore = thnStore.getFollowing();
+ }
+ if (pla2.battle == null) {
+ if ((pla1.isPlayer() && pla2.isPlayer()) && (pla1.clan.equals("none") || pla2.clan.equals("none"))) {
+ pla1.chatMessage("Players who are not in clans cannot fight other players.");
+ return;
+ }
+ if (pla2.isPlayer() && overMerchant(pla2.x, pla2.y) != null) {
+ pla1.chatMessage("You cannot attack players who are shopping.");
+ return;
+ }
+ if (pla2.isPlayer() && overPlayerMerchant(pla2.x, pla2.y) != null) {
+ pla1.chatMessage("You cannot attack players who are shopping.");
+ return;
+ }
+ // FIXME: locks?
+ battleList.add(new Battle(pla1, pla2, this));
+ return;
+ } else {
+ if (pla2.battleSide == 1) {
+ thnStore = pla1;
+ while (thnStore != null) {
+ if (thnStore.battle == null) {
+ pla2.battle.addToBattle(thnStore, 2);
+ }
+ thnStore = thnStore.getFollowing();
+ }
+ thnStore = pla1.getMaster();
+ while (thnStore != null) {
+ if (thnStore.battle == null) {
+ pla2.battle.addToBattle(thnStore, 2);
+ }
+ thnStore = thnStore.getMaster();
+ }
+ } else {
+ thnStore = pla1;
+ while (thnStore != null) {
+ if (thnStore.battle == null) {
+ pla2.battle.addToBattle(thnStore, 1);
+ }
+ thnStore = thnStore.getFollowing();
+ }
+ thnStore = pla1.getMaster();
+ while (thnStore != null) {
+ if (thnStore.battle == null) {
+ pla2.battle.addToBattle(thnStore, 1);
+ }
+ thnStore = thnStore.getMaster();
+ }
+ }
+// pla2.batBattle.chatMessage("\t"+pla1.strName+" has joined the battle.");
+ return;
+ }
+ }
+
+ // Not used
+ @Deprecated
+ public Sign getSign(String inName) {
+ int i;
+ Sign sgnStore;
+ for (i = 0; i < signList.size(); i++) {
+ sgnStore = (Sign) signList.get(i);
+ if (inName.equals(sgnStore.name)) {
+ return sgnStore;
+ }
+ }
+ return null;
+ }
+
+ public LivingThing getPet(String name) {
+ // FIXME: hash map?
+ for (LivingThing pet : petList) {
+ if (name.equalsIgnoreCase(pet.name)) {
+ return pet;
+ }
+ }
+ return null;
+ }
+
+ public LivingThing getPlayer(String name) {
+ name = name.toLowerCase();
+
+ return playersByName.get(name);
+ }
+
+ public Faction getFaction(String name) {
+ Faction faction;
+
+ faction = factionMap.get(name);
+ if (faction == null) {
+ faction = new Faction(name, this);
+ factionMap.put(name, faction);
+ }
+ return faction;
+ }
+
+ public LivingThing getMobFromVct(String inName) {
+ // FIXME: hash map?
+ synchronized (mobList) {
+ for (Mob mob : mobList) {
+ if (mob.name.equals(inName)) {
+ return mob;
+ }
+ }
+ }
+ return null;
+ }
+
+ // FIXME: io on prop as per Item
+ Prop getProp(String strName) {
+ Prop prpStore = null;
+ try {
+ RandomAccessFile rafPropDef = new RandomAccessFile("defProps/" + strName, "r");
+ prpStore = new Prop(getID(), strName);
+ String strStore = rafPropDef.readLine();
+ while (!(strStore == null || strStore.equals("."))) {
+ if (strStore.equalsIgnoreCase("description")) {
+ prpStore.description = rafPropDef.readLine();
+ } else if (strStore.equalsIgnoreCase("image")) {
+ prpStore.intImage = Integer.parseInt(rafPropDef.readLine());
+ }
+ strStore = rafPropDef.readLine();
+ }
+ rafPropDef.close();
+ } catch (Exception e) {
+ log.printError("getProp():While trying to get prop \"" + strName + "\"", e);
+ }
+ return prpStore;
+ }
+
+ // Unused
+ @Deprecated
+ Prop getPropFromVct(String inName) {
+ try {
+ int i = 0;
+ Prop prpStore;
+ while (true) {
+ prpStore = (Prop) propList.get(i);
+ if (prpStore.name.equals(inName)) {
+ return prpStore;
+ }
+ i++;
+ }
+ } catch (Exception e) {
+ log.printError("getPropFromVct():While trying to get prop \"" + inName + "\"", e);
+ }
+ return null;
+ }
+
+ // Unused
+ @Deprecated
+ Prop getPropFromVctAndRemove(String inName) {
+ try {
+ int i = 0;
+ Prop prpStore;
+ while (true) {
+ prpStore = (Prop) propList.get(i);
+ if (prpStore.name.equals(inName)) {
+ //vctProps.remove(i);
+ removeDuskObject(prpStore);
+ return prpStore;
+ }
+ i++;
+ }
+ } catch (Exception e) {
+ log.printError("getPropFromVctAndRemove():While trying to get prop \"" + inName + "\"", e);
+ }
+ return null;
+ }
+
+ @Deprecated
+ public Condition getCondition(String inName) {
+ try {
+ return Condition.getCondition(inName);
+ } catch (Exception e) {
+ log.printError("getCondition():Parsing condition \"" + inName + "\"", e);
+ }
+ return null;
+ }
+
+ int getSpellPercent(String strName) {
+ try {
+ RandomAccessFile rafSpell = new RandomAccessFile("defSpells/" + strName, "r");
+ SpellGroup grpStore = getSpellGroup(rafSpell.readLine());
+ rafSpell.close();
+ return grpStore.getSpellPercent(strName);
+ } catch (Exception e) {
+ log.printError("getSpellPercent():While trying to get info on spell \"" + strName + "\"", e);
+ }
+ return -1;
+ }
+
+ // FIXME: do i/o in SpellGroup
+ @Deprecated
+ public SpellGroup getSpellGroup(String strName) {
+ SpellGroup group;
+ String key = strName.toLowerCase();
+
+ group = spellGroupList.get(key);
+ if (group == null) {
+ group = new SpellGroup(strName);
+ try (RandomAccessFile rafSpellGroup = new RandomAccessFile("defSpellGroups/" + strName, "r")) {
+ String strStore = rafSpellGroup.readLine();
+ while (strStore != null && !strStore.equals("") && !strStore.equals(".")) {
+ group.vctSpells.add(strStore);
+ strStore = rafSpellGroup.readLine();
+ }
+ spellGroupList.put(key, group);
+ } catch (IOException e) {
+ log.printError("trying to read spell group file for \"" + strName + "\"", e);
+ group = null;
+ }
+ }
+ return group;
+ }
+
+ // FIXME: move this to Item
+ @Deprecated
+ public Item getItem(String inName) {
+ try {
+ return Item.getItem(getID(), inName);
+ } catch (IOException ex) {
+ log.printError("getItem():Parsing item \"" + inName + "\"", ex);
+ return null;
+ }
+ }
+
+ // Appears unused
+ @Deprecated
+ Item getItemFromVct(String inName) {
+ try {
+ int i;
+ Item itmStore;
+ StringTokenizer tokName = new StringTokenizer(inName, " ");
+ String strStore = tokName.nextToken();
+ i = Integer.parseInt(strStore);
+ strStore = inName.substring(strStore.length() + 1, inName.length());
+ itmStore = (Item) itemList.get(i);
+ if (itmStore.name.equals(strStore)) {
+ return itmStore;
+ }
+ } catch (Exception e) {
+ log.printError("getItemFromVct():For item \"" + inName + "\"", e);
+ }
+ return null;
+ }
+
+ // Appears unused
+ @Deprecated
+ Item getItemFromVctAndRemove(String inName) {
+ try {
+ int i;
+ Item itmStore;
+ StringTokenizer tokName = new StringTokenizer(inName, " ");
+ String strStore = tokName.nextToken();
+ i = Integer.parseInt(strStore);
+ strStore = inName.substring(strStore.length() + 1, inName.length());
+ itmStore = (Item) itemList.get(i);
+ if (itmStore.name.equals(strStore)) {
+ //vctItems.remove(i);
+ removeDuskObject(itmStore);
+ return itmStore;
+ }
+ } catch (Exception e) {
+ log.printError("getItemFromVctAndRemove():For item \"" + inName + "\"", e);
+ }
+ return null;
+ }
+
+ void playSound(int sfxid, int locx, int locy) {
+ for (TileMap.MapData md : map.range(locx, locy, viewrange)) {
+ for (DuskObject o : md.entities) {
+ if (o.isLivingThing()) {
+ LivingThing lt = (LivingThing) o;
+ if (lt.isPlayer()) {
+ lt.playSFX(sfxid);
+ }
+ }
+ }
+ }
+ }
+
+ public boolean canMoveTo(int inLocX, int inLocY, LivingThing thnStore) {
+ int i;
+ LivingThing thnStore2;
+ Script scrStore;
+ boolean blnStore;
+
+ if (!map.inside(inLocX, inLocY))
+ return false;
+
+ for (DuskObject o : map.getEntities(inLocX, inLocY, null)) {
+ if (o.isLivingThing()) {
+ thnStore2 = (LivingThing) o;
+ if (!canMoveThrougLivingThing(thnStore, thnStore2))
+ return false;
+ }
+ }
+ try {
+ scrStore = new Script("defCanMoveScripts/" + inLocX + "_" + inLocY, this, false);
+ scrStore.varVariables.addVariable("trigger", thnStore);
+ blnStore = scrStore.rewindAndParseScript();
+ scrStore.close();
+ return blnStore;
+ } catch (Exception e) {
+ }
+ try {
+ scrStore = (Script) tileCanMove.get((int) map.getTile(inLocX, inLocY));
+ synchronized (scrStore) {
+ scrStore.varVariables.clearVariables();
+ scrStore.varVariables.addVariable("trigger", thnStore);
+ blnStore = scrStore.rewindAndParseScript();
+ }
+ return blnStore;
+ } catch (Exception e) {
+ //e.printStackTrace();
+ }
+ return false;
+ }
+
+ boolean canSee(int inLocX, int inLocY, LivingThing thnStore) {
+ int i;
+ LivingThing thnStore2;
+ DuskObject objStore = null;
+ Script scrStore;
+ boolean blnStore;
+ try {
+ scrStore = new Script("defCanSeeScripts/" + inLocX + "_" + inLocY, this, false);
+ scrStore.varVariables.addVariable("trigger", thnStore);
+ blnStore = scrStore.rewindAndParseScript();
+ scrStore.close();
+ return blnStore;
+ } catch (Exception e) {
+ }
+ try {
+ scrStore = (Script) tileCanSee.get((int) map.getTile(inLocX, inLocY));
+ synchronized (scrStore) {
+ scrStore.varVariables.clearVariables();
+ scrStore.varVariables.addVariable("trigger", thnStore);
+ blnStore = scrStore.rewindAndParseScript();
+ }
+ return blnStore;
+ } catch (Exception e) {
+ }
+ return false;
+ }
+
+ // TODO: Move this to map, then everything that uses it can be elsewhere
+ // Following by Randall Leeds and Tom Weingarten
+ // map/iterator version by notzed
+ public boolean canSeeTo(LivingThing thing, int destX, int destY) {
+ if (Math.abs(thing.x - destX) > viewrange || Math.abs(thing.y - destY) > viewrange) {
+ return false;
+ }
+
+ if (!blnLineOfSight) {
+ return true;
+ }
+
+ for (TileMap.MapData md : map.look(thing.x, thing.y, destX, destY)) {
+ if (!canSee(md.x, md.y, thing))
+ return false;
+ }
+ return true;
+ /*
+ int tempX = thing.x;
+ int tempY = thing.y;
+
+ // TODO: put looking stuff on map
+ // TODO: put path finding on map
+ // FIXME: this exception stuff is just used for bounds checking ... not good
+ // FIXME: logic could be improved using directions
+ try {
+ while (!(Math.abs(tempX - destX) < 2 && Math.abs(tempY - destY) < 2)) {
+ if (Math.abs(tempX - destX) > Math.abs(tempY - destY)) {
+ if (tempX > destX) {
+ if (!(canSee(tempX - 1, tempY, thing))) {
+ return false;
+ }
+ tempX--;
+ } else {
+ if (!(canSee(tempX + 1, tempY, thing))) {
+ return false;
+ }
+ tempX++;
+ }
+ } else if (Math.abs(tempX - destX) < Math.abs(tempY - destY)) {
+ if (tempY > destY) {
+ if (!(canSee(tempX, tempY - 1, thing))) {
+ return false;
+ }
+ tempY--;
+ } else {
+ if (!(canSee(tempX, tempY + 1, thing))) {
+ return false;
+ }
+ tempY++;
+ }
+ } else {
+ if (tempX > destX && tempY > destY) {
+ if (!(canSee(tempX - 1, tempY - 1, thing))) {
+ return false;
+ }
+ tempX--;
+ tempY--;
+ } else if (tempX < destX && tempY < destY) {
+ if (!(canSee(tempX + 1, tempY + 1, thing))) {
+ return false;
+ }
+ tempX++;
+ tempY++;
+ } else if (tempX > destX && tempY < destY) {
+ if (!(canSee(tempX - 1, tempY + 1, thing))) {
+ return false;
+ }
+ tempX--;
+ tempY++;
+ } else {
+ if (!(canSee(tempX + 1, tempY - 1, thing))) {
+ return false;
+ }
+ tempX++;
+ tempY--;
+ }
+ }
+ }
+ } catch (Exception e) {
+ return false;
+ }
+
+ return true;
+ * */
+ }
+ //End contributed portion
+
+ public Merchant overMerchant(int x, int y) {
+ for (DuskObject o : map.getEntities(x, y, null)) {
+ if (o.isMerchant()) {
+ return (Merchant) o;
+ }
+ }
+ return null;
+ }
+
+ public PlayerMerchant overPlayerMerchant(int x, int y) {
+ for (DuskObject o : map.getEntities(x, y, null)) {
+ if (o.isPlayerMerchant()) {
+ return (PlayerMerchant) o;
+ }
+ }
+ return null;
+ }
+
+ synchronized void changeMap(int locx, int locy, short value) {
+ if (value < 0 || value > tileCanMove.size()) {
+ log.printMessage(Log.INFO, "Invalid value passed to changeMap(" + locx + "," + locy + "," + value + ")");
+ return;
+ }
+ if (!map.inside(locx, locy)) {
+ log.printMessage(Log.INFO, "Invalid location to changeMap(" + locx + "," + locy + "," + value + ")");
+ return;
+ }
+ map.setTile(locx, locy, value);
+ blnMapHasChanged = true;
+ updateMap(locx, locy);
+ }
+
+ synchronized void resizeMap(int x, int y) {
+ map.resize(x, y);
+ for (LivingThing lt : playersByName.values()) {
+ lt.resizeMap();
+ }
+ blnMapHasChanged = true;
+ }
+
+ void saveMap() {
+ if (blnSavingGame) {
+ return;
+ }
+ try {
+ blnSavingGame = true;
+ StringTokenizer tknStore;
+ Mob mobStore;
+ Item itmStore;
+ Sign sgnStore;
+ Merchant mrcStore;
+ Prop prpStore;
+ File deleteme;
+ RandomAccessFile rafFile;
+ int i,
+ i2;
+ if (blnMapHasChanged) {
+ log.printMessage(Log.ALWAYS, "Saving map...");
+ map.saveMap(new File("shortmap"));
+ String strMapLog = "shortmap_redraw";
+ PrintStream psMap = new PrintStream(new FileOutputStream(strMapLog, true), true);
+ psMap.println("# Map Saved");
+ psMap.close();
+ blnMapHasChanged = false;
+ }
+
+ if (blnMobListChanged) {
+ log.printMessage(Log.ALWAYS, "Saving mobs...");
+ synchronized (mobList) {
+ deleteme = new File("mobs");
+ deleteme.delete();
+ rafFile = new RandomAccessFile("mobs", "rw");
+ for (Mob mob : mobList) {
+ if (mob.blnOneUse == false) {
+ if (mob.level == -1) {
+ rafFile.writeBytes("mob2.3\n" + mob.name + "\n" + mob.originalX + "\n" + mob.originalY + "\n");
+ } else {
+ rafFile.writeBytes(mob.name + "\n" + mob.level + "\n" + mob.originalX + "\n" + mob.originalY + "\n");
+ }
+ }
+ }
+ rafFile.close();
+ }
+ blnMobListChanged = false;
+ }
+
+ if (blnSignListChanged) {
+ log.printMessage(Log.ALWAYS, "Saving signs...");
+ synchronized (signList) {
+ deleteme = new File("signs");
+ deleteme.delete();
+ rafFile = new RandomAccessFile("signs", "rw");
+ for (Sign sign : signList) {
+ rafFile.writeBytes(sign.strMessage + "\n" + sign.x + "\n" + sign.y + "\n");
+ }
+ rafFile.close();
+ }
+ blnSignListChanged = false;
+ }
+
+ if (blnMerchantListChanged) {
+ log.printMessage(Log.ALWAYS, "Saving merchants...");
+ synchronized (merchantList) {
+ deleteme = new File("merchants");
+ deleteme.delete();
+ try (RandomAccessFile out = new RandomAccessFile("merchants", "rw")) {
+ // FIXME: i/o on object
+ for (Merchant m : merchantList) {
+ out.writeBytes(m.x + "\n" + m.y + "\n");
+ for (i2 = 0; i2 < m.items.size(); i2++) {
+ out.writeBytes((String) m.items.get(i2) + "\n");
+ }
+ out.writeBytes("end\n");
+ }
+ }
+ }
+ blnMerchantListChanged = false;
+ }
+
+ if (blnPropListChanged) {
+ log.printMessage(Log.ALWAYS, "Saving props...");
+ synchronized (propList) {
+ deleteme = new File("props");
+ deleteme.delete();
+ rafFile = new RandomAccessFile("props", "rw");
+ for (Prop prop : propList) {
+ rafFile.writeBytes(prop.name + "\n" + prop.x + "\n" + prop.y + "\n");
+ }
+ rafFile.close();
+ }
+ blnPropListChanged = false;
+ }
+
+ if (blnVariableListChanged) {
+ log.printMessage(Log.ALWAYS, "Saving global variables...");
+ synchronized (varVariables) {
+ deleteme = new File("globals");
+ deleteme.delete();
+ rafFile = new RandomAccessFile("globals", "rw");
+ for (Variable varStore : varVariables.vctVariables.values()) {
+ if (varStore.isString() || varStore.isNumber()) {
+ rafFile.writeBytes(varStore.strName + "\n");
+ rafFile.writeBytes(varStore.bytType + "\n");
+ rafFile.writeBytes(varStore.objData + "\n");
+ }
+ }
+ rafFile.close();
+ }
+ blnVariableListChanged = false;
+ }
+ log.printMessage(Log.ALWAYS, "Saved game settings without error");
+ } catch (Exception e) {
+ log.printError("saveMap():While saving game settings", e);
+ }
+ blnSavingGame = false;
+ }
+
+ void backupMap() {
+ try {
+ StringTokenizer tknStore;
+ Mob mobStore;
+ Item itmStore;
+ Sign sgnStore;
+ Merchant mrcStore;
+ Prop prpStore;
+ synchronized (map) {
+ File deleteme;
+ RandomAccessFile rafFile;
+ int i, i2;
+
+ map.saveMap(new File("backup/shortmap.backup"));
+
+ deleteme = new File("backup/mobs.backup");
+ deleteme.delete();
+ rafFile = new RandomAccessFile("backup/mobs.backup", "rw");
+ synchronized (mobList) {
+ for (Mob mob : mobList) {
+ if (mob.blnOneUse == false) {
+ tknStore = new StringTokenizer(mob.name, " ");
+ rafFile.writeBytes(tknStore.nextToken() + "\n" + mob.level + "\n" + mob.originalX + "\n" + mob.originalY + "\n");
+ }
+ }
+ }
+ rafFile.close();
+
+ deleteme = new File("backup/signs.backup");
+ deleteme.delete();
+ rafFile = new RandomAccessFile("backup/signs.backup", "rw");
+ for (Sign sign : signList) {
+ rafFile.writeBytes(sign.strMessage + "\n" + sign.x + "\n" + sign.y + "\n");
+ }
+ rafFile.close();
+
+ deleteme = new File("backup/merchants.backup");
+ deleteme.delete();
+ rafFile = new RandomAccessFile("backup/merchants.backup", "rw");
+ for (Merchant m : merchantList) {
+ rafFile.writeBytes(m.x + "\n" + m.y + "\n");
+ for (i2 = 0; i2 < m.items.size(); i2++) {
+ rafFile.writeBytes((String) m.items.get(i2) + "\n");
+ }
+ rafFile.writeBytes("end\n");
+ }
+ rafFile.close();
+
+ deleteme = new File("backup/props.backup");
+ deleteme.delete();
+ rafFile = new RandomAccessFile("backup/props.backup", "rw");
+ for (Prop prop : propList) {
+ rafFile.writeBytes(prop.name + "\n" + prop.x + "\n" + prop.y + "\n");
+ }
+ rafFile.close();
+ }
+ log.printMessage(Log.ALWAYS, "Backed up game settings without error");
+ } catch (Exception e) {
+ log.printError("backupMap():While backing up settings", e);
+ }
+ }
+
+ @Deprecated
+ DuskObject getDuskObject(int x, int y, String name) {
+ //synchronized (entities) {
+ // return DuskObject.find(entities[x][y], name);
+ //}
+ for (DuskObject o : map.getEntities(x, y, null)) {
+ if (o.name.equalsIgnoreCase(name))
+ return o;
+
+ }
+ return null;
+ }
+
+ // must have objEntities locked
+ @Deprecated
+ private void pushDuskObject(DuskObject o) {
+ map.addEntity(o);
+ }
+
+ @Deprecated
+ private void popDuskObject(DuskObject o) {
+ map.removeEntity(o);
+ }
+
+ public void addDuskObject(DuskObject obj) {
+ if (obj.isLivingThing()) {
+ LivingThing lt = (LivingThing) obj;
+ if (!lt.isLoaded) {
+ return;
+ }
+ if (obj instanceof Mob) {
+ synchronized (mobList) {
+ mobList.add((Mob) obj);
+ }
+ blnMobListChanged = true;
+ } else if (lt.isPet()) {
+ petList.add(lt);
+ }
+ } else if (obj.isItem()) {
+ itemList.add((Item) obj);
+ } else if (obj.isSign()) {
+ signList.add((Sign) obj);
+ blnSignListChanged = true;
+ } else if (obj.isMerchant()) {
+ merchantList.add((Merchant) obj);
+ blnMerchantListChanged = true;
+ } else if (obj.isProp()) {
+ propList.add((Prop) obj);
+ blnPropListChanged = true;
+ }
+
+
+ pushDuskObject(obj);
+ addEntity(obj);
+ }
+
+ /**
+ * When a mob is killed, it isn't really removed, but the player needs
+ * to know about it.
+ *
+ * This 'cheats' by removing it from the game but temporarily
+ * corrupting the mob index.
+ *
+ * @param obj
+ */
+ public void mobKilled(Mob obj) {
+ notifyRemoved(obj);
+ popDuskObject(obj);
+ }
+
+ public void removeDuskObject(DuskObject obj) {
+ if (obj.isLivingThing()) {
+ LivingThing lt = (LivingThing) obj;
+ if (!lt.isLoaded) {
+ return;
+ }
+ if (lt.isMob()) {
+ synchronized (mobList) {
+ mobList.remove(obj);
+ }
+ blnMobListChanged = true;
+ } else if (lt.isPet()) {
+ petList.remove(obj);
+ }
+ } else if (obj.isItem()) {
+ itemList.remove(obj);
+ } else if (obj.isSign()) {
+ signList.remove(obj);
+ blnSignListChanged = true;
+ } else if (obj.isMerchant()) {
+ merchantList.remove(obj);
+ blnMerchantListChanged = true;
+ } else if (obj.isProp()) {
+ propList.remove(obj);
+ blnPropListChanged = true;
+ }
+
+ notifyRemoved(obj);
+ popDuskObject(obj);
+ }
+
+ public Iterable<TileMap.MapData> visibleMap(int x, int y) {
+ return map.range(x, y, viewrange);
+ }
+
+ /**
+ * Move a living thing, updating any other living things within range
+ *
+ * @param thing
+ * @param inlocx
+ * @param inlocy
+ * @param dir
+ */
+ // FIXME: now i think this probably needs to be moved back to livingthing ...
+ public void moveDuskObject(LivingThing thing, int inlocx, int inlocy, MessageType dir) {
+ for (TileMap.MapData md : map.range(thing.x, thing.y, viewrange)) {
+ for (DuskObject o : md.entities) {
+ if (o.isLivingThing()) {
+ LivingThing lt = (LivingThing) o;
+ if (lt.isPlayer()) {
+ boolean canSee = canSeeTo(lt, inlocx, inlocy)
+ && (!thing.isLivingThing()
+ || canSeeLivingThing(lt, thing));
+
+ if (canSee) {
+ // Add/update it if now visible
+ lt.addEntity(thing);
+ lt.send(dir, thing.ID + "\n");
+ } else {
+ // Remove it if it isn't
+ lt.removeEntity(thing.ID);
+ }
+ } else if (lt.isMob()) {
+ // Is this true?
+ Mob thnMob = (Mob) lt;
+ thnMob.blnCanSeePlayer = true;
+ }
+ }
+ }
+ }
+ // Move it from cell to cell
+ popDuskObject(thing);
+ thing.x = inlocx;
+ thing.y = inlocy;
+ pushDuskObject(thing);
+ //addDuskObject(objIn);
+ }
+
+ /**
+ * Find a visible object of the given name.
+ *
+ * Name may also be the id.
+ *
+ * @param thing
+ * @param name
+ * @return
+ */
+ public DuskObject findVisibleObject(LivingThing thing, String name) {
+ int number = 0;
+ int byid = -1;
+
+ // First see if this finding an object by unique id.
+ // Since .. the server and client have different ideas about "id numbers" (FFS)
+ try {
+ byid = Integer.valueOf(name);
+ number = 0;
+ } catch (NumberFormatException e) {
+ }
+
+ if (byid == -1) {
+ int i = name.indexOf(".");
+ if (i != -1) {
+ try {
+ number = Integer.parseInt(name.substring(0, i));
+ name = name.substring(i + 1, name.length());
+ } catch (NumberFormatException e) {
+ number = 0;
+ }
+ }
+ }
+ //Search surrounding area
+
+ for (TileMap.MapData md : map.range(thing.x, thing.y, viewrange)) {
+ for (DuskObject o : md.entities) {
+ if (byid == o.ID
+ || (byid == -1 && o.name.equalsIgnoreCase(name))) {
+ if ((!o.isLivingThing()
+ || canSeeLivingThing(thing, (LivingThing) o))
+ && canSeeTo(thing, o.x, o.y)) {
+ if (number == 0) {
+ return o;
+ } else {
+ number--;
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ void updateMap(int locx, int locy) {
+ for (TileMap.MapData md : map.range(locx, locy, viewrange)) {
+ for (DuskObject o : md.entities) {
+ if (o.isLivingThing()) {
+ LivingThing lt = (LivingThing) o;
+ if (lt.isPlayer()) {
+ lt.updateMap();
+ }
+ }
+ }
+ }
+ }
+
+ public void run() {
+ log.printMessage(Log.ALWAYS, "Mob ticks = " + lngMobTicks);
+ log.printMessage(Log.ALWAYS, "Player ticks = " + lngPlayerTicks);
+ log.printMessage(Log.ALWAYS, "Starting Ticks");
+ int tick = 0,
+ i;
+ LivingThing thnStore,
+ thnStore2;
+ Battle batStore;
+ long lngTime = System.currentTimeMillis(),
+ lngPause = 0;
+ while (true) {
+ try {
+ //250 milliseconds per tick
+ lngPause = lngPlayerTicks - (System.currentTimeMillis() - lngTime);
+ if (lngPause > 0) {
+ Thread.currentThread().sleep(lngPause);
+ }
+ lngTime = System.currentTimeMillis();
+ if (tick % 73 == 0) {
+ for (LivingThing pet : petList) {
+ if (pet.battle == null) {
+ if (pet.isSleeping) {
+ pet.hp += 3 + (pet.cons + pet.consbon);
+ if (pet.hp > (pet.maxhp + pet.hpbon)) {
+ pet.hp = (pet.maxhp + pet.hpbon);
+ }
+ pet.mp += 3 + (pet.wisd + pet.wisdbon);
+ if (pet.mp > (pet.maxmp + pet.mpbon)) {
+ pet.mp = (pet.maxmp + pet.mpbon);
+ }
+ } else {
+ pet.hp += 1 + ((pet.cons + pet.consbon) / 2);
+ if (pet.hp > (pet.maxhp + pet.hpbon)) {
+ pet.hp = (pet.maxhp + pet.hpbon);
+ }
+ pet.mp += 1 + ((pet.wisd + pet.wisdbon) / 2);
+ if (pet.mp > (pet.maxmp + pet.mpbon)) {
+ pet.mp = (pet.maxmp + pet.mpbon);
+ }
+ }
+ }
+ if (pet.getMaster() != null) {
+ if (!pet.getMaster().isWorking) {
+ pet.close();
+ continue;
+ }
+ boolean blnTmpShouldSave = pet.isSaveNeeded;
+ pet.getMaster().updateStats();
+ pet.isSaveNeeded = blnTmpShouldSave;
+ } else {
+ pet.close();
+ continue;
+ }
+ pet.savePlayer();
+ }
+ }
+ for (LivingThing pet : petList) {
+ pet.moveTick();
+ }
+ //Following code submitted by Randall Leeds, revised by Tom Weingarten:
+ for (LivingThing lt : playersByName.values()) {
+ if (!lt.isWorking) {
+ //thnStore.closeNoMsgPlayer();
+ continue;
+ }
+ if (!lt.isSaveable) {
+ continue;
+ }
+ if (lt.noChannel > 0 && tick % 4 == 0) {
+ lt.noChannel--;
+ }
+ lt.moveTick();
+ if (tick % 73 == 0) {
+ if (lt.battle == null) {
+ if (lt.isSleeping) {
+ lt.hp += 3 + (lt.cons + lt.consbon);
+ if (lt.hp > (lt.maxhp + lt.hpbon)) {
+ lt.hp = (lt.maxhp + lt.hpbon);
+ }
+ lt.mp += 3 + (lt.wisd + lt.wisdbon);
+ if (lt.mp > (lt.maxmp + lt.mpbon)) {
+ lt.mp = (lt.maxmp + lt.mpbon);
+ }
+ } else {
+ lt.hp += 1 + ((lt.cons + lt.consbon) / 2);
+ if (lt.hp > (lt.maxhp + lt.hpbon)) {
+ lt.hp = (lt.maxhp + lt.hpbon);
+ }
+ lt.mp += 1 + ((lt.wisd + lt.wisdbon) / 2);
+ if (lt.mp > (lt.maxmp + lt.mpbon)) {
+ lt.mp = (lt.maxmp + lt.mpbon);
+ }
+ }
+ lt.updateInfo();
+ lt.savePlayer();
+ }
+ }
+ }
+ //End of code submitted by Randall Leeds
+
+ if (tick % 10 == 0) {
+ for (i = 0; i < battleList.size(); i++) {
+ batStore = (Battle) battleList.get(i);
+ if (batStore.blnRunning == false) {
+ battleList.remove(i);
+ i--;
+ } else {
+ batStore.run();
+ }
+ }
+ }
+ if (tick > 72) {
+ tick = 0;
+ synchronized (mobList) {
+ for (Mob mob : mobList) {
+ if (mob.battle == null) {
+ // FIXME: magic number
+ if (mob.x != -6) {
+ mob.hp += 1 + (mob.cons / 2);
+ if (mob.hp > mob.maxhp) {
+ mob.hp = mob.maxhp;
+ }
+ mob.mp += 1 + (mob.wisd / 2);
+ if (mob.mp > mob.maxmp) {
+ mob.mp = mob.maxmp;
+ }
+ } else {
+ mob.hp++;
+ if (mob.hp > 0) {
+ mob.hp = mob.maxhp;
+ mob.mp = mob.maxmp;
+ mob.changeLocBypass(mob.originalX, mob.originalY);
+ }
+ }
+ }
+ }
+ }
+ for (Faction f : factionMap.values()) {
+ f.saveFactionData();;
+ }
+ }
+ tick++;
+ } catch (Exception e) {
+ log.printError("DuskEngine.run():at ticks", e);
+ }
+ }
+ }
+
+ /**
+ * Script helpers
+ */
+ public boolean canSeeLivingThing(LivingThing seeing, LivingThing seen) {
+ if (scrCanSeeLivingThing != null) {
+ synchronized (scrCanSeeLivingThing) {
+ scrCanSeeLivingThing.varVariables.clearVariables();
+ scrCanSeeLivingThing.varVariables.addVariable("seeing", seeing);
+ scrCanSeeLivingThing.varVariables.addVariable("seen", seen);
+ return scrCanSeeLivingThing.rewindAndParseScript();
+ }
+ } else {
+ return true;
+ }
+ }
+
+ public boolean canMoveThrougLivingThing(LivingThing moving, LivingThing blocking) {
+ if (scrCanMoveThroughLivingThing != null) {
+ synchronized (scrCanMoveThroughLivingThing) {
+ scrCanMoveThroughLivingThing.varVariables.clearVariables();
+ scrCanMoveThroughLivingThing.varVariables.addVariable("moving", moving);
+ scrCanMoveThroughLivingThing.varVariables.addVariable("blocking", blocking);
+ return scrCanMoveThroughLivingThing.rewindAndParseScript();
+ }
+ } else {
+ return true;
+ }
+ }
+
+ public void onStart(LivingThing trigger) {
+ try {
+ if (scrOnStart != null) {
+ synchronized (scrOnStart) {
+ scrOnStart.varVariables.clearVariables();
+ scrOnStart.varVariables.addVariable("trigger", trigger);
+ scrOnStart.runScript();
+ }
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ /**
+ * Temporarily ban an ip address
+ *
+ * @param strIP
+ */
+ public void banAddress(String strIP) {
+ synchronized (bannedIPMap) {
+ bannedIPMap.put(strIP.toLowerCase(), System.currentTimeMillis());
+ }
+ }
+
+ public boolean isBanned(String ip) {
+ synchronized (bannedIPMap) {
+ return bannedIPMap.containsKey(ip.toLowerCase());
+ }
+ }
+
+ public void clearBanned() {
+ synchronized (bannedIPMap) {
+ bannedIPMap.clear();;
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Special thanks to:
+ * Randall Leeds
+ * Vittorio Alberto Floris
+ * Ian Macphail
+ *
+ * Changes
+ */
+package duskz.server;
+
+import duskz.server.entity.LivingThing;
+import java.net.Socket;
+import java.net.ServerSocket;
+
+/**
+ * DuskServer contains the main method for the game.
+ * It handles incoming network connections and passes
+ * them to DuskEngine.
+ *
+ * @author Tom Weingarten
+ */
+public class DuskServer implements Runnable {
+
+ ServerSocket srvServer;
+ Socket sckStore;
+ DuskEngine engGame = null;
+ TrackerThread tracker = null;
+ SaveThread savThread = null;
+ TickThread ticks = null;
+ Thread thrEngine = null,
+ thrTracker = null,
+ thrSave = null,
+ thrTicks = null;
+
+ /**
+ * Creates a new DuskServer object;
+ */
+ public static void main(String args[]) {
+ System.out.println("Loading...");
+ DuskServer MainServer = new DuskServer();
+ Thread thrAccept = new Thread(MainServer);
+ thrAccept.setName("DuskServer");
+ System.out.println("Ready for connections.");
+ thrAccept.start();
+ }
+
+ /**
+ * Creates a DuskEngine object, then a ServerSocket object, then
+ * starts a new thread to accept incoming connections.
+ */
+ public DuskServer() {
+ engGame = new DuskEngine();
+ thrEngine = new Thread(engGame);
+ thrEngine.setName("DuskEngine");
+ thrEngine.start();
+ if (engGame.tracker) {
+ tracker = new TrackerThread(engGame);
+ thrTracker = new Thread(tracker);
+ thrTracker.setName("Tracker");
+ thrTracker.start();
+ }
+ savThread = new SaveThread(engGame);
+ thrSave = new Thread(savThread);
+ thrSave.setName("Save");
+ thrSave.start();
+ ticks = new TickThread(engGame);
+ thrTicks = new Thread(ticks);
+ thrTicks.setName("Ticks");
+ thrTicks.start();
+
+ try {
+ srvServer = new ServerSocket(engGame.port, 25);
+ } catch (Exception e) {
+ engGame.log.printError("DuskServer():Creating server socket", e);
+ engGame.log.printMessage(Log.ALWAYS, "Shutting Down");
+ System.exit(0);
+ }
+ }
+
+ /**
+ * Accepts incoming connections.
+ */
+ public void run() {
+ LivingThing thnStore = null;
+ while (true) {
+ try {
+ sckStore = srvServer.accept();
+ sckStore.setSoTimeout(30000);
+
+ thnStore = new LivingThing(sckStore, engGame);
+ Thread thrLivingThing = new Thread(thnStore);
+ thrLivingThing.setName("LivingThing(new)");
+ thrLivingThing.start();
+ } catch (Exception e) {
+ engGame.log.printError("DuskServer.run()", e);
+ engGame.log.printMessage(Log.ALWAYS, "Shutting Down");
+ System.exit(0);
+ return;
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server;
+
+import duskz.server.entity.TileMap.MapData;
+import duskz.server.entity.Mob;
+import duskz.server.entity.LivingThing;
+import duskz.server.entity.DuskObject;
+import java.io.*;
+import java.util.Vector;
+import java.lang.Math;
+
+/**
+ * a Faction represents a group of mobs.
+ *
+ * @author Tom Weingarten
+ */
+public class Faction {
+
+ final public String strName;
+ Vector vctRelations;
+ DuskEngine game;
+ boolean blnHasChanged = false;
+
+ public Faction(String inName, DuskEngine inGame) {
+ strName = inName;
+ game = inGame;
+ vctRelations = new Vector(0);
+ parseFactionData();
+ }
+
+ void parseFactionData() {
+ RandomAccessFile rafFile = null;
+ try {
+ rafFile = new RandomAccessFile("factions/" + strName, "r");
+ String strStore = rafFile.readLine();
+ while (!(strStore == null || strStore.equals("."))) {
+ if (strStore.equalsIgnoreCase("relation")) {
+ vctRelations.addElement(new Relation(rafFile.readLine().toLowerCase(), Double.valueOf(rafFile.readLine()).doubleValue()));
+ }
+ strStore = rafFile.readLine();
+ }
+ rafFile.close();
+ } catch (Exception e) {
+ game.log.printError("parseFactionData()", e);
+ }
+ }
+
+ synchronized void saveFactionData() {
+ /*
+ ** Only save faction data if it has changed.
+ */
+ if (!blnHasChanged) {
+ return;
+ }
+ int i;
+ RandomAccessFile rafFile;
+ try {
+ rafFile = new RandomAccessFile("factions/" + strName, "rw");
+ Relation relStore;
+ for (i = 0; i < vctRelations.size(); i++) {
+ relStore = (Relation) vctRelations.elementAt(i);
+ rafFile.writeBytes("relation\n" + relStore.strName.toLowerCase() + "\n" + relStore.dblLevel + "\n");
+ }
+ rafFile.writeBytes(".\n");
+ rafFile.close();
+ } catch (Exception e) {
+ game.log.printError("saveFactionData()", e);
+ }
+ blnHasChanged = false;
+ }
+
+ double getRelationValue(String strName) {
+ Relation relStore;
+ for (int i = 0; i < vctRelations.size(); i++) {
+ relStore = (Relation) vctRelations.elementAt(i);
+ if (strName.equalsIgnoreCase(relStore.strName)) {
+ if (i > 100) {
+ vctRelations.removeElementAt(i);
+ vctRelations.insertElementAt(relStore, 0);
+ }
+ return relStore.dblLevel;
+ }
+ }
+ return 0; //if no set relation, impartial
+ }
+
+ Relation getRelation(String strName) {
+ Relation relStore;
+ for (int i = 0; i < vctRelations.size(); i++) {
+ relStore = (Relation) vctRelations.elementAt(i);
+ if (strName.equalsIgnoreCase(relStore.strName)) {
+ if (i > 100) {
+ vctRelations.removeElementAt(i);
+ vctRelations.insertElementAt(relStore, 0);
+ }
+ return relStore;
+ }
+ }
+ return null;
+ }
+
+ void killedBy(LivingThing thnStore, LivingThing thnAttacker) {
+ if (game.blnAI) {
+ double dblOldLevel;
+ Relation relStore = getRelation(thnAttacker.name);
+ if (relStore == null) {
+ relStore = new Relation(thnAttacker.name, 0);
+ vctRelations.addElement(relStore);
+ dblOldLevel = 2;
+ } else {
+ dblOldLevel = relStore.dblLevel;
+ }
+ int delta = thnAttacker.getCharacterPoints() - thnStore.getCharacterPoints();
+ /* Uses an optimized form of the function:
+ ((1.03^delta) + (1.03^-delta)) / (2 + (1.03^delta) + (1.03^-delta))
+ */
+ if (delta == 0) {
+ relStore.dblLevel -= (.5) * (1D + relStore.dblLevel);
+ } else if (delta > 0) {
+ relStore.dblLevel -= ((((Math.pow(1.03, delta)) / (Math.pow(1.03, delta) + 2))) / 2) * (1 + relStore.dblLevel);
+ } else {
+ relStore.dblLevel -= ((Math.pow(1.03, (-1 * delta)) / (Math.pow(1.03, (-1 * delta)) + 2)) / 2) * (1 + relStore.dblLevel);
+ }
+ if (!(thnAttacker.clan == null || thnAttacker.clan.equals("none"))) {
+ relStore = getRelation(thnAttacker.clan);
+ if (relStore == null) {
+ relStore = new Relation(thnAttacker.clan, 0);
+ vctRelations.addElement(relStore);
+ }
+ if (delta == 0) {
+ relStore.dblLevel -= (.5) * (1 + relStore.dblLevel);
+ } else if (delta > 0) {
+ relStore.dblLevel -= ((((Math.pow(1.03, delta)) / (Math.pow(1.03, delta) + 1)) + 1) / 2) * (1 + relStore.dblLevel);
+ } else {
+ relStore.dblLevel -= ((((Math.pow(1.03, (-1 * delta))) / (Math.pow(1.03, (-1 * delta) + 1))) + 1) / 2) * (1 + relStore.dblLevel);
+ }
+ }
+ if (relStore.dblLevel != dblOldLevel) {
+ blnHasChanged = true;
+ }
+ }
+ }
+
+ void runAI(Mob mob) {
+ if (!game.blnAI) {
+ mob.blnCanSeePlayer = false;
+ return;
+ }
+
+ //Battle AI (inside Battle class)
+ if (mob.battle != null) {
+ return;
+ }
+
+ // FIXME: can this be moved to DuskEngine somehow?
+
+ //Default AI
+ int intConfidence = 0;
+ LivingThing enemy = null;
+ Mob mobStore;
+ double enemyrelation = 0;
+ boolean visiblePlayer = false;
+ for (MapData md : game.map.range(mob.x, mob.y, game.viewrange - 1)) {
+ for (DuskObject o : md.entities) {
+ if (o.isLivingThing()) {
+ LivingThing lt = (LivingThing) o;
+ boolean visible = game.canSeeLivingThing(mob, lt);
+
+ if (visible && game.canSeeTo(mob, lt.x, lt.y)) {
+ if (lt.isPlayer()) {
+ visiblePlayer = true;
+ double relation = getRelationValue(lt.name);
+ if (!(lt.clan == null || lt.clan.equals("none"))) {
+ relation = (relation + getRelationValue(lt.clan)) / 2;
+ }
+ if (relation < 0) {
+ if (enemy == null) {
+ enemy = lt;
+ enemyrelation = relation;
+ } else {
+ if (enemyrelation < relation) {
+ enemy = lt;
+ enemyrelation = relation;
+ }
+ }
+ }
+ intConfidence += relation * lt.getTotalPoints();
+ }
+ if (lt.isMob()) {
+ double relation;
+
+ mobStore = (Mob) lt;
+ if (mobStore.name.equals(mob.name)) {
+ relation = mobStore.dblGroupRelation;
+ } else {
+ relation = getRelationValue(mobStore.name);
+ }
+ intConfidence += relation * mobStore.getTotalPoints();
+ if (relation < 0) {
+ if (enemy == null) {
+ enemy = mobStore;
+ enemyrelation = relation;
+ } else {
+ if (enemyrelation > relation) {
+ enemy = mobStore;
+ enemyrelation = relation;
+ }
+ }
+ }
+ intConfidence += relation * lt.getTotalPoints();
+ }
+ }
+ }
+ }
+ }
+ if (!visiblePlayer) {
+ mob.blnCanSeePlayer = false;
+ return;
+ }
+ mob.blnCanSeePlayer = true;
+ if (enemy != null) {
+ double delta = (mob.getTotalPoints() + intConfidence) * mob.dblBravery * -1 * enemyrelation;
+ int enemycp = enemy.getTotalPoints();
+ //Fight/flee
+ if (enemycp < delta) {
+ if (enemycp > delta - (delta * 0.1 * Math.random())) {
+ return;
+ }
+ //Fight
+ if (enemy.tileDistance(mob) <= mob.getRangeWithBonus()) {
+ System.out.println(mob.name + " close enough, going into battle distance: " + enemy.distance(mob) + " range: " + mob.getRangeWithBonus());
+ // close enough to attack, so stop moving
+ mob.clearMoveQueue();
+ game.newBattle(mob, enemy);
+ /*
+ try {
+ // TODO: just call duskEngine.newBattle directly?
+ Commands.parseCommand(mob, game, "a " + enemy.name);
+ } catch (Exception e) {
+ game.log.printError("runAI():" + mob.name + " had an error attacking " + enemy.name, e);
+ }*/
+ } else {
+ mob.goTo(enemy.x, enemy.y, false);
+ }
+ } else {
+ if (enemycp < delta + (delta * 0.1 * Math.random())) {
+ return;
+ }
+ //Flee
+ int destX;
+ int destY;
+ if (enemy.x > mob.x) {
+ destX = mob.x - game.viewrange;
+ } else {
+ destX = mob.x + game.viewrange;
+ }
+ if (enemy.y > mob.y) {
+ destY = mob.y - game.viewrange;
+ } else {
+ destY = mob.y + game.viewrange;
+ }
+ mob.goTo(destX, destY, true);
+ }
+ }
+
+ //If no enemies
+ if ((int) (Math.random() * 25) == 1) {
+ if ((int) (Math.random() * 2) == 1) {
+ if ((int) (Math.random() * 2) == 1) {
+ mob.moveE();
+ } else {
+ mob.moveW();
+ }
+ } else {
+ if ((int) (Math.random() * 2) == 1) {
+ mob.moveS();
+ } else {
+ mob.moveN();
+ }
+ }
+ }
+ }
+}
+
+/**
+ * a Relation represents a feeling held by one faction for another faction, a
+ * player, or a clan. The mob AI bases it's decisions around Relations.
+ *
+ * @author Tom Weingarten
+ */
+class Relation {
+
+ String strName;
+ double dblLevel = 0; //-1 to 1
+
+ Relation(String inName, double inLevel) {
+ strName = inName;
+ dblLevel = inLevel;
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server;
+
+/**
+*GiveItem gives an Item to a LivingThing after they kill a mob.
+*
+*@author Tom Weingarten
+*/
+
+public class GiveItem
+{
+ String strItemName;
+ double dblProbability;
+
+ public GiveItem(String strName, double dblProb)
+ {
+ strItemName = strName;
+ dblProbability = dblProb;
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - attempt at cleanup using modern collections.
+ */
+package duskz.server;
+
+import duskz.server.entity.Item;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+/**
+ * Holds all items, keyed by the item type.
+ */
+public class ItemList extends HashMap<String, LinkedList<Item>> {
+
+ public boolean contains(String strItemName) {
+ return containsKey(strItemName.toLowerCase());
+ }
+
+ public void addElement(Item item) {
+ String key = item.name.toLowerCase();
+ if (contains(key)) {
+ get(key).push(item);
+ } else {
+ LinkedList<Item> list = new LinkedList<>();
+ list.push(item);
+ put(key, list);
+ }
+ }
+
+ public Item removeElement(String name) {
+ name = name.toLowerCase();
+ LinkedList<Item> list = get(name);
+ if (list != null && !list.isEmpty()) {
+ Item item = list.pop();
+ if (list.isEmpty()) {
+ remove(name);
+ }
+ return item;
+ }
+ return null;
+ }
+
+ /*
+ ** This method formats the ItemList for sending to the client
+ ** for display of the player's inventory to the player.
+ */
+ public String print() {
+ StringBuilder invBuffer = new StringBuilder();
+ for (String name : keySet()) {
+ LinkedList<Item> list = get(name);
+ Item item = list.element();
+
+ invBuffer.append("").append((char) 3).append(list.size()).append(" ").append(item.name).append("\n");
+ }
+ return invBuffer.toString();
+ }
+
+ /*
+ ** This method formats the ItemList for saving.
+ ** It generates a String that can later be passed
+ ** to fromString for populating a new ItemList.
+ */
+ public String toString() {
+ StringBuilder invBuffer = new StringBuilder();
+ for (String name : keySet()) {
+ LinkedList<Item> list = get(name);
+
+ for (Item item : list) {
+ invBuffer.append(item.toString()).append("/\n");
+ }
+ }
+ return invBuffer.toString();
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server;
+
+import java.io.PrintStream;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+
+public class Log
+{
+ public static final int ALWAYS = 0;
+ public static final int INFO = 1;
+ public static final int ERROR = 2;
+ public static final int VERBOSE = 3;
+ public static final int DEBUG = 4;
+
+
+ private static final String MSG_ALWAYS = "ALWAYS";
+ private static final String MSG_INFO = "INFO";
+ private static final String MSG_ERROR = "ERROR";
+ private static final String MSG_VERBOSE = "VERBOSE";
+ private static final String MSG_DEBUG = "DEBUG";
+ private static final String LOG_SEP = "::";
+ private PrintStream psOut;
+ private int logLevel = ERROR;
+ private SimpleDateFormat formatter;
+
+ public Log(PrintStream ps)
+ {
+ formatter = new SimpleDateFormat("EEE MMM dd hh:mm:ss yyyy", Locale.getDefault());
+ if (ps != null)
+ {
+ psOut = ps;
+ } else
+ {
+ psOut = System.out;
+ }
+ }
+
+ public void setLogLevel(int newLogLevel)
+ {
+ if ((newLogLevel >= ALWAYS) && (newLogLevel <= DEBUG))
+ {
+ logLevel = newLogLevel;
+ }
+ }
+
+ public int getLogLevel()
+ {
+ return logLevel;
+ }
+
+ private void printTimeStamp(int level)
+ {
+ switch(level)
+ {
+ case ALWAYS:
+ {
+ psOut.print(MSG_ALWAYS+LOG_SEP);
+ break;
+ }
+ case ERROR:
+ {
+ psOut.print(MSG_ERROR+LOG_SEP);
+ break;
+ }
+ case INFO:
+ {
+ psOut.print(MSG_INFO+LOG_SEP);
+ break;
+ }
+ case VERBOSE:
+ {
+ psOut.print(MSG_VERBOSE+LOG_SEP);
+ break;
+ }
+ case DEBUG:
+ {
+ psOut.print(MSG_DEBUG+LOG_SEP);
+ break;
+ }
+ }
+ psOut.print(formatter.format(new Date())+LOG_SEP);
+ if (logLevel >= DEBUG)
+ {
+ psOut.print("thread="+Thread.currentThread().getName()+LOG_SEP);
+ }
+ }
+
+ public void printMessage(int level, String strMessage)
+ {
+ if (level <= logLevel)
+ {
+ printTimeStamp(level);
+ psOut.println(strMessage);
+ }
+ }
+
+ public void printError(String strMessage, Exception e)
+ {
+ if (logLevel >= ERROR)
+ {
+ printTimeStamp(ERROR);
+ psOut.print(strMessage+LOG_SEP);
+ if (logLevel >= DEBUG)
+ {
+ e.printStackTrace(psOut);
+ } else
+ {
+ psOut.println(e.toString());
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package duskz.server;
+
+import java.io.*;
+
+// TODO: wont be needed with javascript
+@Deprecated
+public class RandomAccessString
+{
+ private String strContent = null;
+ private String strCurrentContent = null;
+ private int lCurrentPosition;
+
+ public RandomAccessString(String strFileName)
+ throws IOException
+ {
+ lCurrentPosition = -1;
+ File filView = new File(strFileName);
+ RandomAccessFile rafFile = new RandomAccessFile(filView, "r");
+ byte [] buffer = new byte[(int)rafFile.length()];
+ rafFile.readFully(buffer);
+ rafFile.close();
+ strContent = new String(buffer);
+ strCurrentContent = strContent;
+ lCurrentPosition = 0;
+ }
+
+ public void close()
+ {
+ strContent = null;
+ strCurrentContent = null;
+ }
+
+ public int getFilePointer()
+ {
+ return lCurrentPosition;
+ }
+
+ public void seek(int lSeekPosition)
+ {
+ if (lSeekPosition >= 0 && lSeekPosition < strContent.length())
+ {
+ lCurrentPosition = lSeekPosition;
+ strCurrentContent = strContent.substring(lCurrentPosition);
+ }
+ }
+
+ public String readLine()
+ {
+ if (lCurrentPosition == -1 || strCurrentContent == null)
+ {
+ return null;
+ }
+ String strReturn;
+ int newline = strCurrentContent.indexOf("\r");
+ if (newline == -1)
+ {
+ newline = strCurrentContent.indexOf("\n");
+ if (newline == -1)
+ {
+ strReturn = strCurrentContent;
+ strCurrentContent = null;
+ lCurrentPosition = -1;
+ return strReturn;
+ }
+ }
+ strReturn = strCurrentContent.substring(0, newline);
+ while((newline < strCurrentContent.length())
+ && ((strCurrentContent.charAt(newline) == '\r')
+ || (strCurrentContent.charAt(newline) == '\n')))
+ {
+ newline++;
+ }
+ lCurrentPosition += newline;
+ strCurrentContent = strCurrentContent.substring(newline);
+ return strReturn;
+ }
+
+ public byte readByte()
+ throws IOException
+ {
+ if (lCurrentPosition == -1)
+ {
+ throw new IOException();
+ }
+ byte bReturn = (byte)strContent.charAt(lCurrentPosition);
+ lCurrentPosition++;
+ strCurrentContent = strContent.substring(lCurrentPosition);
+ return bReturn;
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server;
+
+public class SaveThread implements Runnable {
+
+ DuskEngine engGame;
+
+ SaveThread(DuskEngine inGame) {
+ engGame = inGame;
+ }
+
+ public void run() {
+ while (true) {
+ try {
+ Thread.currentThread().sleep(3600000); // sleep for an hour
+ engGame.saveMap(); // save the game
+
+ // Clear out the auto banned IP addresses once an hour
+ engGame.clearBanned();
+
+ } catch (Exception e) {
+ engGame.log.printError("SaveThread.run()", e);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package duskz.server;
+
+/*
+ Portions of code relating to getString() and script
+ parameters by Randall Leeds and Tom Weingarten
+ */
+import duskz.server.entity.Mob;
+import duskz.server.entity.LivingThing;
+import duskz.server.entity.Item;
+import duskz.server.entity.DuskObject;
+import java.io.*;
+import java.util.Vector;
+import java.lang.Math;
+import java.util.List;
+
+/**
+ * Script reads and executes DuskScripts.
+ *
+ * @deprecated is to be replaced by JavaScript
+ * @author Tom Weingarten
+ */
+@Deprecated
+public class Script {
+
+ Vector vctUpdate;
+ Vector vctVisibleUpdate;
+ public VariableSet varVariables;
+// RandomAccessFile rafScript;
+ RandomAccessString rafScript;
+ DuskEngine engGame;
+ String strRead = null;
+ //for script debugging purposes:
+ String strName;
+ int intLine = 0;
+// long lngQuoteFilePointer;
+ int lngQuoteFilePointer;
+
+ public Script(String strIn, DuskEngine inEngine, boolean forcecompile)
+ throws Exception {
+ engGame = inEngine;
+ strName = strIn;
+ if (forcecompile) {
+ File filDelete = new File(strIn + ".dsko");
+ if (filDelete.exists()) {
+ filDelete.delete();
+ }
+ compileScript(strIn);
+ } else {
+ File filCompileCheck = new File(strIn + ".dsko");
+ if (!filCompileCheck.exists()) {
+ compileScript(strIn);
+ }
+ }
+ varVariables = new VariableSet();
+// rafScript = new RandomAccessFile(strIn+".dsko","r");
+ rafScript = new RandomAccessString(strIn + ".dsko");
+ intLine = 0;
+ }
+
+ /**
+ * Helper to run a script with only a trigger arg.
+ *
+ * Silently ignores missing scripts.
+ *
+ * @param name
+ * @param trigger
+ */
+ public static void exec(String name, DuskEngine engGame, LivingThing trigger) {
+ File file = new File(name);
+
+ if (!file.exists())
+ return;
+
+ Script script = null;
+
+ try {
+ script = new Script(name, engGame, false);
+ script.varVariables.addVariable("trigger", trigger);
+ script.runScript();
+ } catch (Exception e) {
+ engGame.log.printError("Executing script " + name, e);
+ } finally {
+ if (script != null) {
+ try {
+ script.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+ // TODO: work out what i want here/clean up every caller
+
+ public static void exec(String name, DuskEngine engGame) {
+ File file = new File(name);
+
+ if (!file.exists())
+ return;
+
+ Script script = null;
+
+ try {
+ script = new Script(name, engGame, false);
+ script.runScript();
+ } catch (Exception e) {
+ engGame.log.printError("Executing script " + name, e);
+ } finally {
+ if (script != null) {
+ try {
+ script.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+
+ synchronized void compileScript(String name)
+ throws Exception {
+ RandomAccessFile rafCompile;
+// rafScript = new RandomAccessFile(name, "r");
+ rafScript = new RandomAccessString(name);
+ try {
+ rafCompile = new RandomAccessFile(name + ".dsko", "rw");
+ } catch (Exception e) {
+ engGame.log.printError("compileScript():Opening " + name + ".dsko file for script " + name, e);
+ return;
+ }
+ try {
+ while (parseScriptForCompile(rafCompile)) {
+ }
+ } catch (Exception e) {
+ engGame.log.printError("compileScript():While running parseScriptForCompile() for script " + name, e);
+ }
+ try {
+ rafCompile.close();
+ } catch (Exception e) {
+ engGame.log.printError("compileScript():While closing .dsko file for script " + name, e);
+ }
+ }
+
+ public void close() {
+ try {
+ rafScript.close();
+ } catch (Exception e) {
+ engGame.log.printError("Script.close():Closing script " + strName, e);
+ }
+ }
+
+ LivingThing getLivingThing(String strName) {
+ try {
+ LivingThing thnStore;
+ if (strName.equalsIgnoreCase("player")) {
+ return engGame.getPlayer(getString());
+ } else if (strName.equalsIgnoreCase("local")) {
+ DuskObject objStore = getLivingThing(getString()).getLocalObject(getString());
+ if (objStore != null && objStore.isLivingThing()) {
+ return ((LivingThing) objStore);
+ }
+ return null;
+ } else if (strName.equalsIgnoreCase("enemy")) {
+ thnStore = getLivingThing(getString());
+ return Battle.getEnemy(thnStore);
+ } else if (strName.equalsIgnoreCase("pet")) {
+ thnStore = getLivingThing(getString());
+ if (thnStore.getFollowing() != null && thnStore.getFollowing().isPet()) {
+ return thnStore.getFollowing();
+ }
+ return null;
+ } else if (strName.equalsIgnoreCase("following")) {
+ thnStore = getLivingThing(getString());
+ if (thnStore.getFollowing() != null && thnStore.getFollowing().isPet()) {
+ return thnStore.getFollowing();
+ } else {
+ return null;
+ }
+ } else if (strName.equalsIgnoreCase("global")) {
+ Variable varStore = engGame.varVariables.getVariable(readScriptForCompile());
+ if (varStore != null && varStore.isLivingThing()) {
+ return (LivingThing) varStore.objData;
+ }
+ }
+ Variable varStore = varVariables.getVariable(strName);
+ if (varStore != null && varStore.isLivingThing()) {
+ return (LivingThing) varStore.objData;
+ }
+ thnStore = engGame.getPlayer(strName);
+ if (thnStore != null) {
+ return thnStore;
+ }
+ thnStore = engGame.getMobFromVct(strName);
+ if (thnStore != null) {
+ return thnStore;
+ }
+ thnStore = engGame.getPet(strName);
+ if (thnStore != null) {
+ return thnStore;
+ }
+ } catch (Exception e) {
+ engGame.log.printError("getLivingThing()", e);
+ }
+ return null;
+ }
+
+ Double getNumber(String strName) {
+ try {
+ return Double.valueOf(strName);
+ } catch (NumberFormatException e) {
+ }
+ if (strName.equalsIgnoreCase("global")) {
+ try {
+ Variable varStore = engGame.varVariables.getVariable(readScriptForCompile());
+ if (varStore != null && varStore.isNumber()) {
+ return (Double) varStore.objData;
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ Variable varStore = varVariables.getVariable(strName);
+ if (varStore != null && varStore.isNumber()) {
+ return (Double) varStore.objData;
+ }
+ return null;
+ }
+
+ private void rewindScript() {
+ intLine = 0;
+ strRead = null;
+ try {
+ rafScript.seek(0);
+ } catch (Exception e) {
+ engGame.log.printError("rewindScript()", e);
+ }
+ }
+
+ public void runScript() {
+ rewindScript();
+ vctUpdate = new Vector(0);
+ vctVisibleUpdate = new Vector(0);
+ while (parseScript()) {
+ }
+ LivingThing thnStore;
+ for (int i = 0; i < vctUpdate.size(); i++) {
+ thnStore = (LivingThing) vctUpdate.elementAt(i);
+ thnStore.updateStats();
+ }
+ for (int i = 0; i < vctVisibleUpdate.size(); i++) {
+ thnStore = (LivingThing) vctVisibleUpdate.elementAt(i);
+ engGame.removeDuskObject(thnStore);
+ engGame.addDuskObject(thnStore);
+ }
+ }
+
+ public void runScript(String strParams) {
+ String strStore2;
+ int i2;
+ try {
+ for (int i = 0; !strParams.equals(""); i++) {
+ if (strParams.startsWith("\"")) {
+ char c, c2;
+
+ strStore2 = "";
+ i2 = 1;
+ while (true) {
+ c = strParams.charAt(i2);
+ if (c == '\\') {
+ c2 = strParams.charAt(i2 + 1);
+ strStore2 += c2;
+ } else if (c == '\"') {
+ i2++;
+ break;
+ } else {
+ strStore2 += c;
+ }
+ i2++;
+ }
+ } else {
+ i2 = strParams.indexOf(" ");
+ if (i2 == -1) {
+ strStore2 = strParams;
+ varVariables.addVariable("param" + i, strStore2);
+ break;
+ } else {
+ strStore2 = strParams.substring(0, i2);
+ }
+ }
+ varVariables.addVariable("param" + i, strStore2);
+ if (strParams.length() > i2) {
+ strParams = strParams.substring(i2 + 1);
+ } else {
+ strParams = "";
+ }
+ }
+ } catch (Exception e) {
+ engGame.log.printError("runScript()", e);
+ }
+ runScript();
+ }
+
+ public boolean rewindAndParseScript() {
+ rewindScript();
+ return parseScript();
+ }
+
+ String readScriptForCompile()
+ throws IOException {
+ String strStore2;
+ if (strRead == null) {
+ // initialize quotation marker before read as we do not know whether
+ // readLine is stripping a cr or a cr/lf pair. This eliminates the
+ // need to use strRead.length() in the calculation.
+ lngQuoteFilePointer = rafScript.getFilePointer();
+ strRead = rafScript.readLine();
+ if (strRead == null) {
+ return null;
+ }
+ // Scan for quotation marks before we can clean up the string with trim
+ int q = strRead.indexOf("\"");
+ if (q != -1) {
+ lngQuoteFilePointer += q + 1;
+ }
+ strRead = strRead.trim();
+ intLine++;
+ }
+ int i = strRead.indexOf(" ");
+ if (i == -1) {
+ strStore2 = strRead;
+ strRead = null;
+ return strStore2;
+ }
+ strStore2 = strRead.substring(0, i).trim();
+ try {
+ strRead = strRead.substring(i + 1, strRead.length());
+ } catch (Exception e) {
+ strRead = null;
+ }
+ return strStore2;
+ }
+
+ String getStringForCompile()
+ throws IOException {
+ String strStore;
+ strStore = readScriptForCompile();
+
+ if (strStore.equals("concat")) {
+ return "concat " + getStringForCompile() + getStringForCompile();
+ }
+
+ if (strStore.equalsIgnoreCase("name")) {
+ return "name " + getStringForCompile();
+ }
+
+ if (strStore.equalsIgnoreCase("enemy")) {
+ return "enemy " + getStringForCompile();
+ }
+
+ if (strStore.equalsIgnoreCase("following")) {
+ return "following " + getStringForCompile();
+ }
+
+ if (strStore.equalsIgnoreCase("clan")) {
+ return "clan " + getStringForCompile();
+ }
+
+ if (strStore.startsWith("\"")) {
+ char c, c2;
+ //Go back to the beginning of the quote
+ rafScript.seek(lngQuoteFilePointer);
+
+ //Read quote into strStore2
+ strStore = "\"";
+ while (true) {
+ c = (char) rafScript.readByte();
+ if (c == '\\') {
+ c2 = (char) rafScript.readByte();
+ strStore += "\\";
+ strStore += c2;
+ } else if (c == '\"') {
+ break;
+ } else if (c == '\n') {
+ strStore += "\n";
+ intLine++;
+ } else if (c == '\r') {
+ strStore += "\n";
+ intLine++;
+ // Skip over LF as this was a CR/LF pair
+ c2 = (char) rafScript.readByte();
+ if (c2 != '\n') {
+ // Back up 1 char if this wasn't a CR/LF pair
+ rafScript.seek(rafScript.getFilePointer() - 1);
+ }
+ } else //If no special characters exist, add it to the string
+ {
+ strStore += c;
+ }
+ }
+ strRead = null; //Delete strRead, readScriptForCompile will recreate it
+ strStore += "\"";
+ return strStore;
+ } else {
+ if (strStore.equalsIgnoreCase("global")) {
+ strStore = getStringForCompile();
+ return "global " + strStore;
+ }
+ }
+ return strStore + " ";
+ }
+
+ String readScript()
+ throws IOException {
+ String strStore = "";
+ char c = (char) rafScript.readByte();
+ while (c != ' ') {
+ strStore += c;
+ c = (char) rafScript.readByte();
+ }
+ return strStore;
+ }
+
+ String getString()
+ throws IOException {
+ String strStore = "";
+// long lngOldFilePointer;
+ int lngOldFilePointer;
+
+ lngOldFilePointer = rafScript.getFilePointer();
+
+ char c = (char) rafScript.readByte();
+
+ //Skip over leading spaces
+ while (c == ' ') {
+ lngOldFilePointer++;
+ c = (char) rafScript.readByte();
+ }
+
+ if (c == '\"') {
+ c = (char) rafScript.readByte();
+ while (c != '\"') {
+ strStore += c;
+ c = (char) rafScript.readByte();
+ }
+ } else {
+ while (c != ' ') {
+ strStore += c;
+ c = (char) rafScript.readByte();
+ }
+ }
+
+ if (strStore.equals("concat")) {
+ return getString() + getString();
+ }
+
+ if (strStore.equalsIgnoreCase("name")) {
+ LivingThing thnStore = getLivingThing(getString());
+ if (thnStore != null) {
+ return thnStore.name;
+ }
+ return "name";
+ }
+
+ if (strStore.equalsIgnoreCase("clan")) {
+ LivingThing thnStore = getLivingThing(getString());
+ if (thnStore != null) {
+ return thnStore.clan;
+ }
+ return "clan";
+ }
+
+ if (strStore.startsWith("\"")) {
+ char c2;
+ //Go back to the beginning of the quote
+ rafScript.seek(lngOldFilePointer + 1);
+
+ //Read quote into strStore2
+ strStore = "";
+ while (true) {
+ c = (char) rafScript.readByte();
+ if (c == '\\') {
+ c2 = (char) rafScript.readByte();
+ strStore += c2;
+ } else if (c == '\"') {
+ break;
+ } else //If no special characters exist, add it to the string
+ {
+ strStore += c;
+ }
+ }
+// try
+// {
+// rafScript.seek(rafScript.getFilePointer()+1);// Why do I need this to skip over ending quote?
+// }catch(EOFException e){}
+ } else {
+ Variable varStore = null;
+ if (strStore.equalsIgnoreCase("global")) {
+ strStore = getString();
+ varStore = engGame.varVariables.getVariable(strStore);
+ } else {
+ varStore = varVariables.getVariable(strStore);
+ }
+ if (varStore == null) {
+ return strStore;
+ } else if (varStore.isString()) {
+ return (String) varStore.objData;
+ } else if (varStore.isLivingThing()) {
+ return strStore;
+ } else if (varStore.isNumber()) {
+ return String.valueOf(((Double) varStore.objData).intValue());
+ }
+ }
+ return strStore;
+ }
+
+ boolean parseScriptForCompile(RandomAccessFile rafCompile)
+ throws Exception {
+ String strStore;
+ try {
+ strStore = readScriptForCompile();
+ if (strStore == null) {
+ return false;
+ }
+ } catch (EOFException e) {
+ return false;
+ }
+ if (strStore.startsWith("#") || strStore.equals(" ")) //comments
+ {
+ strRead = null;
+ intLine++;
+ return true;
+ }
+ if (strStore.equals("!") || strStore.equalsIgnoreCase("not")) //Not, returns the opposite of the next line
+ {
+ rafCompile.writeByte(0);
+ return true;
+ } else if (strStore.equalsIgnoreCase("if")) {
+ rafCompile.writeByte(1);
+ return true;
+ } else if (strStore.equals("end")) {
+ rafCompile.writeByte(2);
+ return true;
+ } else if (strStore.equals(")") || strStore.equals("(")) {
+ return true;
+ } else if (strStore.equalsIgnoreCase("t") || strStore.equalsIgnoreCase("true")) {
+ rafCompile.writeByte(3);
+ return true;
+ } else if (strStore.equalsIgnoreCase("f") || strStore.equalsIgnoreCase("false")) {
+ rafCompile.writeByte(4);
+ return true;
+ } else if (strStore.equalsIgnoreCase("playsound")) {
+ rafCompile.writeByte(5);
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("order")) {
+ rafCompile.writeByte(6);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("hascondition")) {
+ rafCompile.writeByte(7);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("addcondition")) {
+ rafCompile.writeByte(8);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("addconditionwithduration")) {
+ rafCompile.writeByte(9);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("removecondition")) {
+ rafCompile.writeByte(10);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("addflag")) {
+ rafCompile.writeByte(11);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("hasflag")) {
+ rafCompile.writeByte(12);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("removeflag")) {
+ rafCompile.writeByte(13);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("global")) {
+ strStore = getStringForCompile().trim();
+ if (strStore.equalsIgnoreCase("livingthing")) {
+ rafCompile.writeByte(14);
+ rafCompile.writeBytes(readScriptForCompile() + " ");
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("number")) {
+ rafCompile.writeByte(15);
+ rafCompile.writeBytes(readScriptForCompile() + " ");
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("string")) {
+ rafCompile.writeByte(16);
+ rafCompile.writeBytes(readScriptForCompile() + " ");
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ }
+ } else if (strStore.equalsIgnoreCase("livingthing")) {
+ rafCompile.writeByte(17);
+ rafCompile.writeBytes(readScriptForCompile() + " ");
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("number")) {
+ rafCompile.writeByte(18);
+ rafCompile.writeBytes(readScriptForCompile() + " ");
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("string")) {
+ rafCompile.writeByte(19);
+ rafCompile.writeBytes(readScriptForCompile() + " ");
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("or")) {
+ rafCompile.writeByte(20);
+ return true;
+ } else if (strStore.equalsIgnoreCase("and")) {
+ rafCompile.writeByte(21);
+ return true;
+ } else if (strStore.equalsIgnoreCase("<")) {
+ rafCompile.writeByte(22);
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase(">")) {
+ rafCompile.writeByte(23);
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("=")) {
+ rafCompile.writeByte(24);
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("isinbattle")) {
+ rafCompile.writeByte(25);
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("isclan")) {
+ rafCompile.writeByte(26);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("israce")) {
+ rafCompile.writeByte(27);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("hasitem")) {
+ rafCompile.writeByte(28);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("createmob")) {
+ rafCompile.writeByte(29);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("createoneusemob")) {
+ rafCompile.writeByte(30);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("createitem")) {
+ rafCompile.writeByte(31);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("giveitem")) {
+ rafCompile.writeByte(59);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("removeitem")) {
+ rafCompile.writeByte(33);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("iswearing")) {
+ rafCompile.writeByte(34);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("unwear")) {
+ rafCompile.writeByte(35);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("variableisnumber")) {
+ rafCompile.writeByte(36);
+ strStore = getStringForCompile();
+ if (strStore.equalsIgnoreCase("global")) {
+ rafCompile.writeBytes("global ");
+ strStore = getStringForCompile();
+ }
+ rafCompile.writeBytes(strStore);
+ return true;
+ } else if (strStore.equalsIgnoreCase("variableisstring")) {
+ rafCompile.writeByte(37);
+ strStore = getStringForCompile();
+ if (strStore.equalsIgnoreCase("global")) {
+ rafCompile.writeBytes("global ");
+ strStore = getStringForCompile();
+ }
+ rafCompile.writeBytes(strStore);
+ return true;
+ } else if (strStore.equalsIgnoreCase("variableislivingthing")) {
+ rafCompile.writeByte(38);
+ strStore = getStringForCompile();
+ if (strStore.equalsIgnoreCase("global")) {
+ rafCompile.writeBytes("global ");
+ strStore = getStringForCompile();
+ }
+ rafCompile.writeBytes(strStore);
+ return true;
+ } else if (strStore.equalsIgnoreCase("isplayer")) {
+ rafCompile.writeByte(39);
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("ispet")) {
+ rafCompile.writeByte(40);
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("ismob")) {
+ rafCompile.writeByte(41);
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("chat")) {
+ rafCompile.writeByte(42);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("chatc")) {
+ rafCompile.writeByte(43);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("inc")) {
+ rafCompile.writeByte(44);
+ rafCompile.writeBytes(getStringForCompile());
+ strStore = readScriptForCompile();
+ if (strStore.equalsIgnoreCase("hp")) {
+ rafCompile.writeByte(0);
+ }
+ if (strStore.equalsIgnoreCase("maxhp")) {
+ rafCompile.writeByte(1);
+ }
+ if (strStore.equalsIgnoreCase("hpbonus")) {
+ rafCompile.writeByte(2);
+ }
+ if (strStore.equalsIgnoreCase("mp")) {
+ rafCompile.writeByte(3);
+ }
+ if (strStore.equalsIgnoreCase("maxmp")) {
+ rafCompile.writeByte(4);
+ }
+ if (strStore.equalsIgnoreCase("mpbonus")) {
+ rafCompile.writeByte(5);
+ }
+ if (strStore.equalsIgnoreCase("damdone")) {
+ rafCompile.writeByte(6);
+ }
+ if (strStore.equalsIgnoreCase("strength")) {
+ rafCompile.writeByte(7);
+ }
+ if (strStore.equalsIgnoreCase("intelligence")) {
+ rafCompile.writeByte(8);
+ }
+ if (strStore.equalsIgnoreCase("dexterity")) {
+ rafCompile.writeByte(9);
+ }
+ if (strStore.equalsIgnoreCase("wisdom")) {
+ rafCompile.writeByte(10);
+ }
+ if (strStore.equalsIgnoreCase("constitution")) {
+ rafCompile.writeByte(11);
+ }
+ if (strStore.equalsIgnoreCase("strengthbonus")) {
+ rafCompile.writeByte(12);
+ }
+ if (strStore.equalsIgnoreCase("intelligencebonus")) {
+ rafCompile.writeByte(13);
+ }
+ if (strStore.equalsIgnoreCase("dexteritybonus")) {
+ rafCompile.writeByte(14);
+ }
+ if (strStore.equalsIgnoreCase("wisdombonus")) {
+ rafCompile.writeByte(15);
+ }
+ if (strStore.equalsIgnoreCase("constitutionbonus")) {
+ rafCompile.writeByte(16);
+ }
+ if (strStore.equalsIgnoreCase("acbonus")) {
+ rafCompile.writeByte(17);
+ }
+ if (strStore.equalsIgnoreCase("dammodbonus")) {
+ rafCompile.writeByte(18);
+ }
+ if (strStore.equalsIgnoreCase("locx")) {
+ rafCompile.writeByte(19);
+ }
+ if (strStore.equalsIgnoreCase("locy")) {
+ rafCompile.writeByte(20);
+ }
+ if (strStore.equalsIgnoreCase("locxy")) {
+ rafCompile.writeByte(21);
+ rafCompile.writeBytes(parseValueForCompile());
+ }
+ if (strStore.equalsIgnoreCase("exp")) {
+ rafCompile.writeByte(22);
+ }
+ if (strStore.equalsIgnoreCase("cash")) {
+ rafCompile.writeByte(23);
+ }
+ if (strStore.equalsIgnoreCase("skill")) {
+ rafCompile.writeByte(24);
+ rafCompile.writeBytes(getStringForCompile());
+ }
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("set")) {
+ rafCompile.writeByte(45);
+ rafCompile.writeBytes(getStringForCompile());
+ strStore = readScriptForCompile();
+ if (strStore.equalsIgnoreCase("hp")) {
+ rafCompile.writeByte(0);
+ }
+ if (strStore.equalsIgnoreCase("maxhp")) {
+ rafCompile.writeByte(1);
+ }
+ if (strStore.equalsIgnoreCase("hpbonus")) {
+ rafCompile.writeByte(2);
+ }
+ if (strStore.equalsIgnoreCase("mp")) {
+ rafCompile.writeByte(3);
+ }
+ if (strStore.equalsIgnoreCase("maxmp")) {
+ rafCompile.writeByte(4);
+ }
+ if (strStore.equalsIgnoreCase("mpbonus")) {
+ rafCompile.writeByte(5);
+ }
+ if (strStore.equalsIgnoreCase("damdone")) {
+ rafCompile.writeByte(6);
+ }
+ if (strStore.equalsIgnoreCase("strength")) {
+ rafCompile.writeByte(7);
+ }
+ if (strStore.equalsIgnoreCase("intelligence")) {
+ rafCompile.writeByte(8);
+ }
+ if (strStore.equalsIgnoreCase("dexterity")) {
+ rafCompile.writeByte(9);
+ }
+ if (strStore.equalsIgnoreCase("wisdom")) {
+ rafCompile.writeByte(10);
+ }
+ if (strStore.equalsIgnoreCase("constitution")) {
+ rafCompile.writeByte(11);
+ }
+ if (strStore.equalsIgnoreCase("strengthbonus")) {
+ rafCompile.writeByte(12);
+ }
+ if (strStore.equalsIgnoreCase("intelligencebonus")) {
+ rafCompile.writeByte(13);
+ }
+ if (strStore.equalsIgnoreCase("dexteritybonus")) {
+ rafCompile.writeByte(14);
+ }
+ if (strStore.equalsIgnoreCase("wisdombonus")) {
+ rafCompile.writeByte(15);
+ }
+ if (strStore.equalsIgnoreCase("constitutionbonus")) {
+ rafCompile.writeByte(16);
+ }
+ if (strStore.equalsIgnoreCase("acbonus")) {
+ rafCompile.writeByte(17);
+ }
+ if (strStore.equalsIgnoreCase("dammodbonus")) {
+ rafCompile.writeByte(18);
+ }
+ if (strStore.equalsIgnoreCase("locx")) {
+ rafCompile.writeByte(19);
+ }
+ if (strStore.equalsIgnoreCase("locy")) {
+ rafCompile.writeByte(20);
+ }
+ if (strStore.equalsIgnoreCase("locxy")) {
+ rafCompile.writeByte(21);
+ rafCompile.writeBytes(parseValueForCompile());
+ }
+ if (strStore.equalsIgnoreCase("exp")) {
+ rafCompile.writeByte(22);
+ }
+ if (strStore.equalsIgnoreCase("cash")) {
+ rafCompile.writeByte(23);
+ }
+ if (strStore.equalsIgnoreCase("skill")) {
+ rafCompile.writeByte(24);
+ rafCompile.writeBytes(getStringForCompile());
+ }
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("changeTile")) {
+ rafCompile.writeByte(46);
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ rafCompile.writeBytes(parseValueForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("strequals")) {
+ rafCompile.writeByte(47);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("input")) {
+ rafCompile.writeByte(48);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("checkviewable")) {
+ rafCompile.writeByte(49);
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("log")) {
+ rafCompile.writeByte(50);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("gecho")) {
+ rafCompile.writeByte(51);
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("endscript")) {
+ rafCompile.writeByte(4);
+ return true;
+ } else if (strStore.equalsIgnoreCase("chatwindow")) {
+ rafCompile.writeByte(52);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("kill")) {
+ rafCompile.writeByte(53);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("endcommand")) {
+ rafCompile.writeByte(54);
+ return true;
+ } else if (strStore.equalsIgnoreCase("clanleader")) {
+ rafCompile.writeByte(55);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("changeclan")) {
+ rafCompile.writeByte(56);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("floodoff")) {
+ rafCompile.writeByte(57);
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ } else if (strStore.equalsIgnoreCase("battlechat")) {
+ rafCompile.writeByte(58);
+ rafCompile.writeBytes(getStringForCompile());
+ rafCompile.writeBytes(getStringForCompile());
+ return true;
+ }
+ rafCompile.writeBytes(strStore + " ");
+ return true;
+ }
+
+ boolean parseScript() {
+ intLine++;
+ byte bytCommand = 0;
+ try {
+ bytCommand = rafScript.readByte();
+ // Skip over spaces between commands (if any)
+ while (bytCommand == 32) {
+ bytCommand = rafScript.readByte();
+ }
+ switch (bytCommand) {
+ case 0: {
+ if (parseScript()) {
+ return false;
+ }
+ return true;
+ }
+ case 1: {
+ if (!parseScript()) {
+ int ifCount = 1;
+ byte bytStore;
+ while (true) {
+ bytStore = rafScript.readByte();
+ if (bytStore == 1) {
+ ifCount++;
+ } else if (bytStore == 2) {
+ ifCount--;
+ if (ifCount == 0) {
+ break;
+ }
+ }
+ }
+ }
+ return true;
+ }
+ case 2: {
+ return true;
+ }
+ case 3: {
+ return true;
+ }
+ case 4: {
+ return false;
+ }
+ case 5: {
+ engGame.playSound((int) parseValue(), (int) parseValue(), (int) parseValue());
+ return true;
+ }
+ case 6: {
+ LivingThing thnStore = getLivingThing(getString());
+ Commands.parseCommand(thnStore, engGame, getString());
+ return true;
+ }
+ case 7: {
+ return getLivingThing(getString()).hasCondition(getString());
+ }
+ case 8: {
+ getLivingThing(getString()).addCondition(engGame.getCondition(getString()));
+ return true;
+ }
+ case 9: {
+ LivingThing thnStore = getLivingThing(getString());
+ Condition cndStore = engGame.getCondition(getString());
+ cndStore.duration = (int) parseValue();
+ thnStore.addCondition(cndStore);
+ return true;
+ }
+ case 10: {
+ getLivingThing(getString()).removeCondition(getString());
+ return true;
+ }
+ case 11: {
+ LivingThing thnStore = getLivingThing(getString());
+ thnStore.flags.add(getString());
+ if (vctVisibleUpdate != null || vctVisibleUpdate.contains(thnStore)) {
+ vctVisibleUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 12: {
+ LivingThing thnStore = getLivingThing(getString());
+ String strStore2 = getString();
+ for (int i = 0; i < thnStore.flags.size(); i++) {
+ if (strStore2.equalsIgnoreCase((String) thnStore.flags.get(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+ case 13: {
+ LivingThing thnStore = getLivingThing(getString());
+ String strStore2 = getString();
+ for (int i = 0; i < thnStore.flags.size(); i++) {
+ if (strStore2.equalsIgnoreCase((String) thnStore.flags.get(i))) {
+ thnStore.flags.remove(i);
+ if (vctVisibleUpdate != null || vctVisibleUpdate.contains(thnStore)) {
+ vctVisibleUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ }
+ return true;
+ }
+ case 14: {
+ engGame.varVariables.addVariable(readScript(), getLivingThing(getString()));
+ engGame.blnVariableListChanged = true;
+ return true;
+ }
+ case 15: {
+ engGame.varVariables.addVariable(readScript(), parseValue());
+ engGame.blnVariableListChanged = true;
+ return true;
+ }
+ case 16: {
+ engGame.varVariables.addVariable(readScript(), getString());
+ engGame.blnVariableListChanged = true;
+ return true;
+ }
+ case 17: {
+ varVariables.addVariable(readScript(), getLivingThing(getString()));
+ return true;
+ }
+ case 18: {
+ varVariables.addVariable(readScript(), parseValue());
+ return true;
+ }
+ case 19: {
+ varVariables.addVariable(readScript(), getString());
+ return true;
+ }
+ case 20: {
+ return (parseScript() | parseScript());
+ }
+ case 21: {
+ return (parseScript() & parseScript());
+ }
+ case 22: {
+ return (parseValue() < parseValue());
+ }
+ case 23: {
+ return (parseValue() > parseValue());
+ }
+ case 24: {
+ return (parseValue() == parseValue());
+ }
+ case 25: {
+ if (getLivingThing(getString()).battle != null) {
+ return true;
+ }
+ return false;
+ }
+ case 26: {
+ if (getLivingThing(getString()).clan.equalsIgnoreCase(getString())) {
+ return true;
+ }
+ return false;
+ }
+ case 27: {
+ if (getLivingThing(getString()).race.equalsIgnoreCase(getString())) {
+ return true;
+ }
+ return false;
+ }
+ case 28: {
+ if (getLivingThing(getString()).getItem(getString()) != null) {
+ return true;
+ }
+ return false;
+ }
+ case 29: {
+ Mob mobStore = new Mob(getString(), (int) parseValue(), (int) parseValue(), engGame);
+ //engGame.vctMobs.add(mobStore);
+ engGame.addDuskObject(mobStore);
+ return true;
+ }
+ case 30: {
+ Mob mobStore = new Mob(getString(), (int) parseValue(), (int) parseValue(), engGame);
+ mobStore.blnOneUse = true;
+ //engGame.vctMobs.add(mobStore);
+ engGame.addDuskObject(mobStore);
+ return true;
+ }
+ case 31: {
+ Item itmStore = engGame.getItem(getString());
+ itmStore.x = (int) parseValue();
+ itmStore.y = (int) parseValue();
+ engGame.addDuskObject(itmStore);
+ return true;
+ }
+ case 59: {
+ LivingThing thnStore = getLivingThing(getString());
+ String strStore2 = getString();
+ int i = strStore2.indexOf(".");
+ int intNum = 1;
+ if (i != -1) {
+ try {
+ intNum = Integer.parseInt(strStore2.substring(0, i));
+ strStore2 = strStore2.substring(i + 1, strStore2.length());
+ } catch (NumberFormatException e) {
+ intNum = 1;
+ }
+ }
+ Item itmStore = engGame.getItem(strStore2);
+ if (itmStore != null) {
+ // FIXME: put this in addItem() accessor on LivingThing
+ while (intNum > 0) {
+ thnStore.itemList.addElement(itmStore);
+ itmStore.onGetItem(engGame, thnStore);
+ intNum--;
+ }
+ thnStore.updateItems();
+ }
+ return true;
+ }
+ case 33: {
+ LivingThing thnStore = getLivingThing(getString());
+ thnStore.getItemAndRemove(getString());
+ thnStore.updateItems();
+ return true;
+ }
+ case 34: {
+ return getLivingThing(getString()).isWearing(getString());
+ }
+ case 35: {
+ getLivingThing(getString()).unWear(getString());
+ return true;
+ }
+ case 36: {
+ String strStore2 = readScript();
+ Variable varStore = null;
+ if (strStore2.equalsIgnoreCase("global")) {
+ varStore = engGame.varVariables.getVariable(readScript());
+ } else {
+ varStore = varVariables.getVariable(strStore2);
+ }
+ if (varStore != null && varStore.isNumber()) {
+ return true;
+ }
+ return false;
+ }
+ case 37: {
+ String strStore2 = readScript();
+ Variable varStore = null;
+ if (strStore2.equalsIgnoreCase("global")) {
+ varStore = engGame.varVariables.getVariable(readScript());
+ } else {
+ varStore = varVariables.getVariable(strStore2);
+ }
+ if (varStore != null && varStore.isString()) {
+ return true;
+ }
+ return false;
+ }
+ case 38: {
+ String strStore2 = readScript();
+ Variable varStore = null;
+ if (strStore2.equalsIgnoreCase("global")) {
+ varStore = engGame.varVariables.getVariable(readScript());
+ } else {
+ varStore = varVariables.getVariable(strStore2);
+ }
+ if (varStore != null && varStore.isLivingThing()) {
+ return true;
+ }
+ return false;
+ }
+ case 39: {
+ LivingThing thnStore = getLivingThing(getString());
+ if (thnStore != null && thnStore.isPlayer()) {
+ return true;
+ }
+ return false;
+ }
+ case 40: {
+ LivingThing thnStore = getLivingThing(getString());
+ if (thnStore != null && thnStore.isPet()) {
+ return true;
+ }
+ return false;
+ }
+ case 41: {
+ LivingThing thnStore = getLivingThing(getString());
+ if (thnStore != null && thnStore.isMob()) {
+ return true;
+ }
+ return false;
+ }
+ case 42: {
+ LivingThing thnStore = getLivingThing(getString());
+ String strStore2 = getString();
+ int intIndex = strStore2.indexOf("\n");
+ while (intIndex != -1) {
+ thnStore.chatMessage(strStore2.substring(0, intIndex));
+ strStore2 = strStore2.substring(intIndex + 1);
+ intIndex = strStore2.indexOf("\n");
+ }
+ thnStore.chatMessage(strStore2);
+ return true;
+ }
+ case 43: {
+ LivingThing thnStore = getLivingThing(getString());
+ int red = (int) parseValue();
+ int green = (int) parseValue();
+ int blue = (int) parseValue();
+ String strStore2 = getString();
+ int intIndex = strStore2.indexOf("\n");
+ while (intIndex != -1) {
+ thnStore.chatMessage(red, green, blue, strStore2.substring(0, intIndex));
+ strStore2 = strStore2.substring(intIndex + 1);
+ intIndex = strStore2.indexOf("\n");
+ }
+ thnStore.chatMessage(red, green, blue, strStore2);
+ return true;
+ }
+ case 44: {
+ LivingThing thnStore = getLivingThing(getString());
+ bytCommand = rafScript.readByte();
+ switch (bytCommand) {
+ case 0: {
+ // FIXME: hp damage/adjustment if in battle, should send it through as a message
+ thnStore.hp += (int) parseValue();
+ if (thnStore.hp > (thnStore.maxhp + thnStore.hpbon)) {
+ thnStore.hp = (thnStore.maxhp + thnStore.hpbon);
+ }
+ thnStore.updateInfo();
+ return true;
+ }
+ case 1: {
+ thnStore.maxhp += (int) parseValue();
+ thnStore.updateInfo();
+ return true;
+ }
+ case 2: {
+ thnStore.hpbon += (int) parseValue();
+ thnStore.updateInfo();
+ return true;
+ }
+ case 3: {
+ thnStore.mp += (int) parseValue();
+ if (thnStore.mp > (thnStore.maxmp + thnStore.mpbon)) {
+ thnStore.mp = (thnStore.maxmp + thnStore.mpbon);
+ }
+ thnStore.updateInfo();
+ return true;
+ }
+ case 4: {
+ thnStore.maxmp += (int) parseValue();
+ thnStore.updateInfo();
+ return true;
+ }
+ case 5: {
+ thnStore.mpbon += (int) parseValue();
+ thnStore.updateInfo();
+ return true;
+ }
+ case 6: {
+ thnStore.damageDone += (int) parseValue();
+ return true;
+ }
+ case 7: {
+ thnStore.stre += (int) parseValue();
+ if (thnStore.stre > thnStore.stre_limit) {
+ thnStore.stre = thnStore.stre_limit;
+ }
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 8: {
+ thnStore.inte += (int) parseValue();
+ if (thnStore.inte > thnStore.inte_limit) {
+ thnStore.inte = thnStore.inte_limit;
+ }
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 9: {
+ thnStore.dext += (int) parseValue();
+ if (thnStore.dext > thnStore.dext_limit) {
+ thnStore.dext = thnStore.dext_limit;
+ }
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 10: {
+ thnStore.wisd += (int) parseValue();
+ if (thnStore.wisd > thnStore.wisd_limit) {
+ thnStore.wisd = thnStore.wisd_limit;
+ }
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 11: {
+ thnStore.cons += (int) parseValue();
+ if (thnStore.cons > thnStore.cons_limit) {
+ thnStore.cons = thnStore.cons_limit;
+ }
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 12: {
+ thnStore.strebon += (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 13: {
+ thnStore.intebon += (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 14: {
+ thnStore.dextbon += (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 15: {
+ thnStore.wisdbon += (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 16: {
+ thnStore.consbon += (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 17: {
+ thnStore.acbon += (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 18: {
+ thnStore.dammodbon += (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 19: {
+ thnStore.changeLocBypass((int) parseValue() + thnStore.x, thnStore.y);
+ return true;
+ }
+ case 20: {
+ thnStore.changeLocBypass(thnStore.x, (int) parseValue() + thnStore.y);
+ return true;
+ }
+ case 21: {
+ thnStore.changeLocBypass((int) parseValue() + thnStore.x, (int) parseValue() + thnStore.y);
+ return true;
+ }
+ case 22: {
+ thnStore.exp += (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 23: {
+ thnStore.cash += (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 24: {
+ String strStore2 = getString();
+ int intAddValue = (int) parseValue();
+ thnStore.addToSkill(strStore2, intAddValue);
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ }
+ }
+ case 45: {
+
+ LivingThing thnStore = getLivingThing(getString());
+ bytCommand = rafScript.readByte();
+ switch (bytCommand) {
+ case 0: {
+ thnStore.hp = (int) parseValue();
+ if (thnStore.hp > (thnStore.maxhp + thnStore.hpbon)) {
+ thnStore.hp = (thnStore.maxhp + thnStore.hpbon);
+ }
+ thnStore.updateInfo();
+ return true;
+ }
+ case 1: {
+ thnStore.maxhp = (int) parseValue();
+ thnStore.updateInfo();
+ return true;
+ }
+ case 2: {
+ thnStore.hpbon = (int) parseValue();
+ thnStore.updateInfo();
+ return true;
+ }
+ case 3: {
+ thnStore.mp = (int) parseValue();
+ if (thnStore.mp > (thnStore.maxmp + thnStore.mpbon)) {
+ thnStore.mp = (thnStore.maxmp + thnStore.mpbon);
+ }
+ thnStore.updateInfo();
+ return true;
+ }
+ case 4: {
+ thnStore.maxmp = (int) parseValue();
+ thnStore.updateInfo();
+ return true;
+ }
+ case 5: {
+ thnStore.mpbon = (int) parseValue();
+ thnStore.updateInfo();
+ return true;
+ }
+ case 6: {
+ thnStore.damageDone = (int) parseValue();
+ return true;
+ }
+ case 7: {
+ thnStore.stre = (int) parseValue();
+ if (thnStore.stre > thnStore.stre_limit) {
+ thnStore.stre = thnStore.stre_limit;
+ }
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 8: {
+ thnStore.inte = (int) parseValue();
+ if (thnStore.inte > thnStore.inte_limit) {
+ thnStore.inte = thnStore.inte_limit;
+ }
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 9: {
+ thnStore.dext = (int) parseValue();
+ if (thnStore.dext > thnStore.dext_limit) {
+ thnStore.dext = thnStore.dext_limit;
+ }
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 10: {
+ thnStore.wisd = (int) parseValue();
+ if (thnStore.wisd > thnStore.wisd_limit) {
+ thnStore.wisd = thnStore.wisd_limit;
+ }
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 11: {
+ thnStore.cons = (int) parseValue();
+ if (thnStore.cons > thnStore.cons_limit) {
+ thnStore.cons = thnStore.cons_limit;
+ }
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 12: {
+ thnStore.strebon = (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 13: {
+ thnStore.intebon = (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 14: {
+ thnStore.dextbon = (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 15: {
+ thnStore.wisdbon = (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 16: {
+ thnStore.consbon = (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 17: {
+ thnStore.acbon = (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 18: {
+ thnStore.dammodbon = (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 19: {
+ thnStore.changeLocBypass((int) parseValue(), thnStore.y);
+ return true;
+ }
+ case 20: {
+ thnStore.changeLocBypass(thnStore.x, (int) parseValue());
+ return true;
+ }
+ case 21: {
+ thnStore.changeLocBypass((int) parseValue(), (int) parseValue());
+ return true;
+ }
+ case 22: {
+ thnStore.exp = (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 23: {
+ thnStore.cash = (int) parseValue();
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 24: {
+ String strStore2 = getString();
+ int intNewValue = (int) parseValue();
+ thnStore.setSkill(strStore2, intNewValue);
+ if (vctUpdate != null || vctUpdate.contains(thnStore)) {
+ vctUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ }
+ }
+ case 46: {
+ int dbgX, dbgY;
+ short dbgValue;
+ dbgX = (int) parseValue();
+ dbgY = (int) parseValue();
+ dbgValue = (short) parseValue();
+ if (dbgValue == 0) {
+ engGame.log.printMessage(Log.DEBUG, "Script " + strName + " called changeMap with 0 at " + dbgX + "," + dbgY);
+ }
+// engGame.changeMap((int)parseValue(),(int)parseValue(),(short)parseValue());
+ engGame.changeMap(dbgX, dbgY, dbgValue);
+ return true;
+ }
+ case 47: {
+ String strOne = getString();
+ return strOne.equalsIgnoreCase(getString());
+ }
+ case 48: {
+ String strInput = "";
+ LivingThing thnStore = getLivingThing(getString());
+ if (!thnStore.isPlayer()) {
+ engGame.log.printMessage(Log.ERROR, "parseScript():In script " + strName + ", attempt to get input from non-player");
+ return false;
+ }
+ if (true)
+ // FIXME: protocol implementation
+ throw new RuntimeException("cannot ask questions yet");
+ // FIXME: this looks dodgy
+ // FIXME: move to livingthing
+ thnStore.halt();
+ thnStore.stillThere(); // This puts something in the buffer
+ thnStore.stillThere(); // Need to do this twice to ensure thnStore out of read loop
+ thnStore.connectionThread.sleep(750); // wait for it...
+ try {
+ // Empty out the BufferedReader for the answer
+ //while (thnStore.instream.ready()) {
+ // thnStore.instream.read();
+ //}
+ } catch (Exception e) {
+ engGame.log.printError("parseScript():While trying to empty read buffer to get player input", e);
+ }
+ strInput = thnStore.instream.readLine();
+ varVariables.addVariable(getString(), strInput);
+ thnStore.proceed();
+ return true;
+ }
+ case 49: {
+ LivingThing thnStore = getLivingThing(getString());
+ engGame.notifyRemoved(thnStore);
+ engGame.addEntity(thnStore);
+ return true;
+ }
+ case 50: {
+ LivingThing thnStore = getLivingThing(getString());
+ String strStore = getString();
+ if (thnStore == null) {
+ return true;
+ }
+ strStore = strStore.replace('\n', ' ');
+ if (thnStore.isPlayer()) {
+ strStore = "player " + thnStore.name + " " + strStore;
+ } else if (thnStore.isPet()) {
+ strStore = "pet " + thnStore.name + " " + strStore;
+ } else if (thnStore.isMob()) {
+ strStore = "mob " + thnStore.name + " " + strStore;
+ }
+ engGame.log.printMessage(Log.ALWAYS, "ScriptLog:" + strName + ":" + strStore);
+ return true;
+ }
+ case 51: {
+ String strStore = getString();
+ engGame.chatMessage(strStore, "default");
+ return true;
+ }
+ case 52: {
+ LivingThing thnStore = getLivingThing(getString());
+ String strTitle = getString();
+ String strStore2 = getString();
+ String strLine = null;
+ int intIndex = strStore2.indexOf("\n");
+ thnStore.send((char) 20 + strTitle + "\n");
+ while (intIndex != -1) {
+ strLine = strStore2.substring(0, intIndex);
+ thnStore.send(strLine + "\n");
+ strStore2 = strStore2.substring(intIndex + 1);
+ intIndex = strStore2.indexOf("\n");
+ }
+ thnStore.send(strStore2 + "\n");
+ thnStore.send("--EOF--\n");
+ return true;
+ }
+ case 53: {
+ LivingThing thnStore = getLivingThing(getString());
+ if (thnStore == null) {
+ return true;
+ }
+ String strWhat = getString();
+ if (strWhat == null) {
+ return true;
+ }
+ if (thnStore.isPlayer()) {
+ if (engGame.gplosemod != 0) {
+ int gplost = (int) (thnStore.cash * engGame.gplosemod);
+ thnStore.chatMessage("You have lost " + gplost + "gp.");
+ thnStore.cash -= gplost;
+ }
+ if (engGame.explosemod != 0) {
+ int explost = (int) (thnStore.exp * engGame.explosemod);
+ thnStore.chatMessage("You have lost " + explost + "exp.");
+ thnStore.exp -= explost;
+ }
+ engGame.chatMessage(thnStore.name + " has been killed by " + strWhat, "default");
+ if (engGame.scrOnDeath != null && thnStore.isWorking) {
+ engGame.scrOnDeath.varVariables.clearVariables();
+ engGame.scrOnDeath.varVariables.addVariable("trigger", thnStore);
+ engGame.scrOnDeath.runScript();
+ }
+ }
+ return true;
+ }
+ case 54: {
+ LivingThing thnStore = getLivingThing("trigger");
+ if (thnStore != null && thnStore.isLivingThing()) {
+ thnStore.isAlwaysCommands = false;
+ }
+ return true;
+ }
+ case 55: {
+ LivingThing thnStore = getLivingThing(getString());
+ String strClanName = getString();
+ if (engGame.isGoodName(strClanName)) {
+ thnStore.clan = strClanName;
+ if (thnStore.privs < 1) {
+ thnStore.privs = 1;
+ }
+ }
+ return true;
+ }
+ case 56: {
+ LivingThing thnStore = getLivingThing(getString());
+ String strClanName = getString();
+ if (engGame.isGoodName(strClanName)) {
+ thnStore.clan = strClanName;
+ if (thnStore.privs == 1) {
+ thnStore.privs = 0;
+ }
+ }
+ if (vctVisibleUpdate != null || vctVisibleUpdate.contains(thnStore)) {
+ vctVisibleUpdate.addElement(thnStore);
+ }
+ return true;
+ }
+ case 57: {
+ LivingThing thnStore = getLivingThing(getString());
+ thnStore.lastMessageStamp = 0;
+ return true;
+ }
+ case 58: {
+ LivingThing thnStore = getLivingThing(getString());
+ String strStore2 = getString();
+ int intIndex = strStore2.indexOf("\n");
+ while (intIndex != -1) {
+ if (thnStore.battle != null && thnStore.popup) {
+ thnStore.send("" + (char) 33 + strStore2.substring(0, intIndex + 1));
+ } else {
+ thnStore.chatMessage(strStore2.substring(0, intIndex));
+ }
+ strStore2 = strStore2.substring(intIndex + 1);
+ intIndex = strStore2.indexOf("\n");
+ }
+ if (thnStore.battle != null && thnStore.popup) {
+ thnStore.send("" + (char) 33 + strStore2 + "\n");
+ } else {
+ thnStore.chatMessage(strStore2);
+ }
+ return true;
+ }
+ case 32: {
+ return true;
+ }
+ /*case 127:
+ {
+ return false;
+ }*/
+ }
+ } catch (Exception e) {
+ engGame.log.printError("parseScript():While parsing byte(" + bytCommand + ") of script " + strName + " at line " + intLine, e);
+ return false;
+ }
+ engGame.log.printMessage(Log.ERROR, "parseScript():Unknown byte(" + bytCommand + ") parsing script " + strName + " at line " + intLine);
+ return false;
+ }
+
+ private String parseValueForCompile() {
+ try {
+ String strStore = readScriptForCompile();
+ //functions:
+ if (strStore.equals("+")) {
+ return ("+ " + parseValueForCompile() + parseValueForCompile());
+ }
+ if (strStore.equals("-")) {
+ return ("- " + parseValueForCompile() + parseValueForCompile());
+ }
+ if (strStore.equals("*")) {
+ return ("* " + parseValueForCompile() + parseValueForCompile());
+ }
+ if (strStore.equals("/")) {
+ return ("/ " + parseValueForCompile() + parseValueForCompile());
+ }
+ if (strStore.equalsIgnoreCase("skill")) {
+ return "skill " + readScriptForCompile() + " ";
+ }
+ return strStore + " ";
+ } catch (Exception e) {
+ engGame.log.printError("parseValueForCompile():Compiling script " + strName, e);
+ }
+ return null;
+ }
+
+ private double parseValue() {
+ try {
+ String strStore = getString();
+ //functions:
+ if (strStore.equals("+")) {
+ return (parseValue() + parseValue());
+ }
+ if (strStore.equals("-")) {
+ return (parseValue() - parseValue());
+ }
+ if (strStore.equals("*")) {
+ return (parseValue() * parseValue());
+ }
+ if (strStore.equals("/")) {
+ return (parseValue() / parseValue());
+ }
+ //random number:
+ if (strStore.equalsIgnoreCase("rand")) {
+ return Math.random();
+ }
+ //number:
+ Double dblStore = getNumber(strStore);
+ if (dblStore != null) {
+ return dblStore.doubleValue();
+ }
+ //player qualities:
+ LivingThing target = getLivingThing(strStore);
+ strStore = getString();
+
+ if (strStore.equalsIgnoreCase("cp")) {
+ return (target.getCharacterPoints());
+ }
+ if (strStore.equalsIgnoreCase("tp")) {
+ return (target.getTotalPoints());
+ }
+ if (strStore.equalsIgnoreCase("cash")) {
+ return (target.cash);
+ }
+ if (strStore.equalsIgnoreCase("exp")) {
+ return (target.exp);
+ }
+ if (strStore.equalsIgnoreCase("locx")) {
+ return (target.x);
+ }
+ if (strStore.equalsIgnoreCase("locy")) {
+ return (target.y);
+ }
+ if (strStore.equalsIgnoreCase("hp")) {
+ return (target.hp);
+ }
+ if (strStore.equalsIgnoreCase("maxhp")) {
+ return (target.maxhp + target.hpbon);
+ }
+ if (strStore.equalsIgnoreCase("mp")) {
+ return (target.mp);
+ }
+ if (strStore.equalsIgnoreCase("maxmp")) {
+ return (target.maxmp + target.mpbon);
+ }
+ if (strStore.equalsIgnoreCase("stre")) {
+ return (target.stre + target.strebon);
+ }
+ if (strStore.equalsIgnoreCase("dext")) {
+ return (target.dext + target.dextbon);
+ }
+ if (strStore.equalsIgnoreCase("inte")) {
+ return (target.inte + target.intebon);
+ }
+ if (strStore.equalsIgnoreCase("wisd")) {
+ return (target.wisd + target.wisdbon);
+ }
+ if (strStore.equalsIgnoreCase("cons")) {
+ return (target.cons + target.consbon);
+ }
+ if (strStore.equalsIgnoreCase("dammod")) {
+ return target.getDamModWithBonus();
+ }
+ if (strStore.equalsIgnoreCase("ac")) {
+ return target.getArmorModWithBonus();
+ }
+ if (strStore.equalsIgnoreCase("privs")) {
+ return target.privs;
+ }
+ if (strStore.equalsIgnoreCase("skill")) {
+ String strStore2 = getString();
+ int bytStore = target.getSkill(strStore2);
+ if (bytStore == 0) {
+ bytStore = target.getSpell(strStore2);
+ }
+ return bytStore;
+ }
+ if (strStore.equalsIgnoreCase("count")) {
+ String strStore2 = getString();
+ List<Item> list = target.itemList.get(strStore2);
+ long total = 0;
+ if (list != null) {
+ total = list.size();
+ }
+ return total;
+ }
+ } catch (Exception e) {
+ engGame.log.printError("parseValue()", e);
+ }
+ return 0;
+ }
+}
--- /dev/null
+/*/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FilePermission;
+import java.io.FileReader;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.security.cert.Certificate;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ThreadFactory;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.SimpleScriptContext;
+
+/**
+ * Manages the (javascript) engine
+ *
+ * Doing this securely is complicated, so is likely to be buggy and not really
+ * secure ...
+ *
+ * I found I had to create the script engine itself from the same doPrivileged()
+ * invocation or it simply broke the sanboxing. Hence all script execution is
+ * performed from a pool of threads created from the same sandbox.
+ *
+ * Another thread monitors the pool checking for out of control scripts (i.e.
+ * they take too long to run).
+ *
+ * @author notzed
+ */
+public class ScriptManager {
+
+ AccessControlContext ac;
+ ScriptEngine engine;
+ LinkedBlockingDeque<ScriptData> queue = new LinkedBlockingDeque<>();
+ int nthreads = 2;
+ ExecutorService pool;
+ static ThreadLocal<ScriptContext> contexts;
+ // some sort of shit here for monitoring threads
+ HashMap<Thread, Long> active = new HashMap<>();
+
+ public ScriptManager() {
+ Permissions perms = new Permissions();
+ //perms.add(new AllPermission());
+ perms.add(new FilePermission("scripts/*", "read,write"));
+ // perms.add(new NetPermission("*"));
+ //perms.add(new RuntimePermission("accessDeclaredMembers"));
+ // Cast to Certificate[] required because of ambiguity:
+ ProtectionDomain domain = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), perms);
+ ac = new AccessControlContext(new ProtectionDomain[]{domain});
+ }
+
+ public void start() {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ // If the engine is created here it needs to be used here too.
+ ScriptEngineManager factory = new ScriptEngineManager();
+ engine = factory.getEngineByName("JavaScript");
+ contexts = new ThreadLocal<>();
+ pool = Executors.newFixedThreadPool(2, new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(r);
+
+ t.setDaemon(true);
+ return t;
+ }
+ });
+
+ // TOOD: anything else I want to do here? A management/monitoring thread?
+
+ return null;
+ }
+ }, ac);
+
+ new WatchThread().start();
+ }
+
+ public Future<?> runScript(String script, Object... args) {
+ return pool.submit(new ScriptData(script, args));
+ }
+
+ public Future<?> runScript(File script, Object... args) throws FileNotFoundException {
+ return pool.submit(new ScriptData(script, args));
+ }
+
+ synchronized void startJob(Thread t) {
+ active.put(t, System.currentTimeMillis());
+ }
+
+ synchronized void endJob(Thread t) {
+ active.remove(t);
+ }
+
+ synchronized void watchdog() {
+ // So there is no way to interrupt the executing thread!
+ // Well it mozilla code after-all ...
+
+ // So i'm forced to use stop with all its apparent dangers.
+
+ long now = System.currentTimeMillis();
+ for (Entry<Thread, Long> e : active.entrySet()) {
+ if ((now - e.getValue()) > 1000) {
+ System.out.println("Job taking too long, interrupting it!");
+ //e.getKey().interrupt();
+ e.getKey().stop();
+ }
+ }
+ }
+
+ class WatchThread extends Thread {
+
+ public WatchThread() {
+ setDaemon(true);
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ try {
+ sleep(1000);
+
+ watchdog();
+ } catch (InterruptedException ex) {
+ Logger.getLogger(ScriptManager.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ }
+ };
+
+ class ScriptData<T> implements Callable<T> {
+
+ FileReader scriptReader;
+ String script;
+ Map<String, Object> args = new HashMap<>();
+
+ public ScriptData(String script, Object... args) {
+ for (int i = 0; i < args.length; i += 2) {
+ this.args.put((String) args[i], args[i + 1]);
+ }
+ this.script = script;
+ }
+
+ public ScriptData(File scriptFile, Object... args) throws FileNotFoundException {
+ for (int i = 0; i < args.length; i += 2) {
+ this.args.put((String) args[i], args[i + 1]);
+ }
+ this.scriptReader = new FileReader(scriptFile);
+ }
+
+ @Override
+ public T call() throws Exception {
+ T res = null;
+ try {
+ ScriptContext ctx = contexts.get();
+ if (ctx == null) {
+ ctx = new SimpleScriptContext();
+ contexts.set(ctx);
+ }
+ Bindings b = ctx.getBindings(ScriptContext.ENGINE_SCOPE);
+
+ b.clear();
+ b.putAll(args);
+
+ startJob(Thread.currentThread());
+ if (scriptReader != null)
+ res = (T) engine.eval(scriptReader, b);
+ else
+ res = (T) engine.eval(script, b);
+ // lastStart = -1;
+ b.clear();
+ } finally {
+ endJob(Thread.currentThread());
+ if (scriptReader != null)
+ scriptReader.close();
+ }
+ return res;
+ }
+ };
+
+ public static void main(String[] args) {
+ // Lets see if it the security shit works
+ ScriptManager sm = new ScriptManager();
+
+ sm.start();
+
+ Future f;
+
+ try {
+ f = sm.runScript("1;");
+ System.out.println("result = " + f.get());
+ } catch (Exception ex) {
+ ex.printStackTrace(System.out);
+ }
+ try {
+ f = sm.runScript("if (true) 0; else 1;");
+ System.out.println("result = " + f.get());
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+
+ try {
+ String s = "var out = new java.io.FileOutputStream('hack-thread.txt');"
+ + " out.write(65);"
+ + "out.close();"
+ + " println('wrote hack.txt ok');";
+
+ f = sm.runScript(s);
+ System.out.println("result = " + f.get());
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+ try {
+ f = sm.runScript(new File("hack.script"));
+ System.out.println("result = " + f.get());
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+ try {
+ String s = "var out = new java.io.FileInputStream('hack.script');"
+ + "out.close();"
+ + " println('read hack.script ok');";
+
+ f = sm.runScript(s);
+ System.out.println("result = " + f.get());
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+ try {
+ String s = "while (true);";
+ f = sm.runScript(s);
+ System.out.println("result = " + f.get());
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+ try {
+ String s = "while (true);";
+ f = sm.runScript(s);
+ System.out.println("result = " + f.get());
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+ try {
+ String s = "var out = new java.io.FileOutputStream('scripts/newscript');"
+ + " out.write(65);"
+ + "out.close();"
+ + " println('wrote scripts/newscript ok');";
+
+ f = sm.runScript(s);
+ System.out.println("result = " + f.get());
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+ try {
+ String s = "while (true);";
+ f = sm.runScript(s);
+ System.out.println("result = " + f.get());
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - modernised collections
+ */
+package duskz.server;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * SpellGroup contains all the spells in one group. It provides methods to
+ * decide how much a spell will cost the player to cast.
+ *
+ * @author Tom Weingarten
+ */
+public class SpellGroup {
+
+ public final String strName;
+ public final List<String> vctSpells = new ArrayList<>();
+
+ public SpellGroup(String inName) {
+ strName = inName;
+ }
+
+ int getSpellPercent(String strName) {
+ int i = getSpellNumber(strName);
+ if (i > 0) {
+ i = (100 * i) / (vctSpells.size() - 1);
+ }
+ return i;
+ /*
+ String strStore;
+ for (int i = 0; i < vctSpells.size(); i++) {
+ strStore = (String) vctSpells.elementAt(i);
+ if (strStore.equals(strName)) {
+ if (i == 0) {
+ return 0;
+ } else {
+ return (100 * i) / (vctSpells.size() - 1);
+ }
+ }
+ }
+ return -1;*/
+ }
+
+ public int getSpellNumber(String strName) {
+ return vctSpells.indexOf(strName);
+ /*
+ String strStore;
+ for (int i = 0; i < vctSpells.size(); i++) {
+ strStore = (String) vctSpells.elementAt(i);
+ if (strStore.equals(strName)) {
+ return i;
+ }
+ }
+ return -1;*/
+ }
+
+ public String spellList(int percent) {
+ String strStore;
+
+ if (vctSpells.isEmpty()) {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder();
+
+ strStore = (String) vctSpells.get(0);
+ if (strStore == null) {
+ return "";
+ }
+ sb.append(" ").append((110 - percent) / 2).
+ append(" mp) ").
+ append(strStore).append("\n");
+ for (int i = 1; i < vctSpells.size(); i++) {
+ if (percent < (100 * i) / (vctSpells.size() - 1)) {
+ break;
+ }
+ strStore = (String) vctSpells.get(i);
+ sb.append(" ").append((110 - (percent - (100 * i) / (vctSpells.size() - 1))) / 2)
+ .append(" mp) ").append(strStore).append("\n");
+ }
+ return sb.toString();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - Modernisation, fixed some locking issues
+ */
+package duskz.server;
+
+import duskz.server.entity.Mob;
+import duskz.server.entity.LivingThing;
+import java.util.Iterator;
+
+public class TickThread implements Runnable {
+
+ DuskEngine game;
+ long now = System.currentTimeMillis(),
+ delay = 0;
+ int tick = 0;
+
+ TickThread(DuskEngine inGame) {
+ this.game = inGame;
+ }
+
+ public void run() {
+ while (true) {
+ try {
+ //1000 milliseconds(1 second) per tick
+ delay = 1000L - (System.currentTimeMillis() - now);
+ if (delay > 0) {
+ Thread.currentThread().sleep(delay);
+ }
+ now = System.currentTimeMillis();
+
+ // FIXME: similar code is also in DuskEngine, all unlocked??
+
+ synchronized (game.mobList) {
+ for (Mob mob : game.mobList) {
+ // FIXME: remove magic number!!
+ if (mob.x == -6) {
+ mob.hp++;
+ if (mob.hp > -1) {
+ mob.changeLocBypass(mob.originalX, mob.originalY);
+ mob.hp = mob.maxhp;
+ }
+ } else {
+ try {
+ if (game.blnAI && mob.blnCanSeePlayer && (mob.fctFaction != null)) {
+ mob.fctFaction.runAI(mob);
+ }
+ } catch (Exception e) {
+ mob.blnCanSeePlayer = false;
+ game.log.printError("TickThread.run():While trying to runAI for mob \"" + mob.name + "\".", e);
+ }
+ mob.moveTick();
+ }
+ }
+ }
+ for (LivingThing lt : game.checkConditionList) {
+ for (Iterator<Condition> it = lt.conditions.iterator(); it.hasNext();) {
+ Condition cond = it.next();
+ if (cond.ticksPast >= cond.occurance) {
+ cond.onOccurance(game, lt);
+ if (cond.duration > 0) {
+ cond.duration--;
+ }
+ if (cond.duration == 0) {
+ cond.onEnd(game, lt);
+ it.remove();
+ }
+ cond.ticksPast = 1;
+ } else {
+ cond.ticksPast++;
+ }
+ }
+ }
+
+ if (tick > 120) {
+ tick = 0;
+ }
+ tick++;
+ } catch (Exception e) {
+ game.log.printError("ThreadTicks.run()", e);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server;
+
+import duskz.server.entity.LivingThing;
+import java.net.DatagramSocket;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+
+public class TrackerThread implements Runnable {
+
+ DuskEngine engGame;
+ DatagramSocket sckTracker;
+
+ TrackerThread(DuskEngine inGame) {
+ engGame = inGame;
+ }
+
+ void initializeTracker() {
+ if (engGame.tracker && sckTracker == null) {
+ try {
+ engGame.log.printMessage(Log.ALWAYS, "Communicating with tracker");
+ sckTracker = new DatagramSocket(engGame.trackerport);
+ sckTracker.setSoTimeout(0); //no timeout
+ String s1 = "\000" + engGame.trackername;
+ DatagramPacket datagrampacket = new DatagramPacket(s1.getBytes(), s1.length());
+ datagrampacket.setAddress(InetAddress.getByName("dusk.wesowin.org"));
+ datagrampacket.setPort(7520);
+ sckTracker.send(datagrampacket);
+ s1 = "\002" + engGame.port;
+ datagrampacket.setData(s1.getBytes());
+ datagrampacket.setLength(s1.length());
+ sckTracker.send(datagrampacket);
+ if (!engGame.site.equals("none")) {
+ String s2 = "\003" + engGame.site;
+ datagrampacket.setData(s2.getBytes());
+ datagrampacket.setLength(s2.length());
+ sckTracker.send(datagrampacket);
+ }
+ engGame.tracker = true;
+ } catch (Exception e) {
+ engGame.log.printError("initializeTracker():Failed to contact tracker, disabling", e);
+ sckTracker = null;
+ engGame.tracker = false;
+ }
+ }
+ }
+
+ void updateTrackerUsers() {
+ if (!engGame.tracker) {
+ return;
+ }
+
+ try {
+ int count = 0;
+ for (LivingThing thnStore : engGame.playersByName.values()) {
+ if (!(thnStore.privs > 2 && thnStore.hasCondition("invis"))) {
+ count++;
+ }
+ }
+ String s = "\001" + count;
+ DatagramPacket datagrampacket = new DatagramPacket(s.getBytes(), s.length());
+ datagrampacket.setAddress(InetAddress.getByName("dusk.wesowin.org"));
+ datagrampacket.setPort(7520);
+ sckTracker.send(datagrampacket);
+ } catch (Exception e) {
+ engGame.log.printError("updateTrackerUsers()", e);
+ }
+ }
+
+ void pingTracker() {
+ if (!engGame.tracker) {
+ return;
+ }
+
+ DatagramPacket pckStore = new DatagramPacket(new byte[1], 1);
+
+ try {
+ pckStore.setAddress(InetAddress.getByName("dusk.wesowin.org"));
+ pckStore.setPort(7520);
+ pckStore.setData("\005".getBytes());
+ pckStore.setLength(1);
+ sckTracker.send(pckStore);
+ } catch (Exception e) {
+ engGame.log.printError("pingTracker():While communicating with tracker", e);
+ sckTracker = null;
+ engGame.tracker = false;
+ }
+ }
+
+ void removeFromTracker() {
+ if (!engGame.tracker) {
+ return;
+ }
+
+ try {
+ String s = "\004";
+ DatagramPacket datagrampacket = new DatagramPacket(s.getBytes(), s.length());
+ datagrampacket.setAddress(InetAddress.getByName("dusk.wesowin.org"));
+ datagrampacket.setPort(7520);
+ sckTracker.send(datagrampacket);
+ } catch (Exception e) {
+ engGame.log.printError("removeFromTracker()", e);
+ }
+ }
+
+ public void run() {
+ if (!engGame.tracker) {
+ return;
+ }
+
+ engGame.log.printMessage(Log.ALWAYS, "Starting tracker thread");
+
+ initializeTracker();
+
+ while (engGame.tracker) {
+ try {
+ Thread.currentThread().sleep(300000);
+ } catch (Exception e) {
+ engGame.log.printError("TrackerThread.run()", e);
+ }
+ updateTrackerUsers();
+ pingTracker();
+ }
+
+ removeFromTracker();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - separated out from VariableSet for public access
+ */
+package duskz.server;
+
+/**
+ * Holder for variables.
+ *
+ * TODO: make this OO. Will need fixing for javascript.
+ *
+ * @author notzed
+ */
+public class Variable {
+
+ String strName;
+ Object objData;
+ byte bytType;
+ public final static byte NUMBER = 0;
+ public final static byte STRING = 1;
+ public final static byte THING = 2;
+
+ public Variable(String strName, Object objData, byte bytType) {
+ this.strName = strName;
+ this.objData = objData;
+ this.bytType = bytType;
+ }
+
+ public double doubleValue() {
+ return (Double) objData;
+ }
+
+ public int intValue() {
+ return ((Number) objData).intValue();
+ }
+
+ //0-Number
+ //1-String
+ //2-LivingThing
+ //3-Item
+ boolean isNumber() {
+ if (bytType == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ boolean isString() {
+ if (bytType == 1) {
+ return true;
+ }
+ return false;
+ }
+
+ boolean isLivingThing() {
+ if (bytType == 2) {
+ return true;
+ }
+ return false;
+ }
+
+ boolean isItem() {
+ if (bytType == 3) {
+ return true;
+ }
+ return false;
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - modernised java, separated out Variable.
+ */
+package duskz.server;
+
+import duskz.server.entity.LivingThing;
+import java.util.HashMap;
+
+/**
+ * Contains a set of variables for use in a DuskScript. Variables may be of type
+ * number, livingthing, or string.
+ *
+ * @author Tom Weingarten
+ */
+public class VariableSet {
+
+ //Vector vctVariables;
+ public final HashMap<String, Variable> vctVariables = new HashMap<>();
+
+ public VariableSet() {
+ }
+
+ public void clearVariables() {
+ vctVariables.clear();
+ }
+
+ protected void addVariable(Variable v) {
+ String n = v.strName.toLowerCase();
+ if (n.equals("name")
+ || n.equals("clan")
+ || n.equals("concat")) {
+// engGame.log.printMessage(Log.ERROR, "addVariable():You cannot create a variable with the name \""+strName+"\".");
+ return;
+ }
+ vctVariables.put(n, v);
+ }
+
+ public void addVariable(String strName, Double objIn) {
+ addVariable(new Variable(strName, objIn, Variable.NUMBER));
+ }
+
+ public void addVariable(String strName, double objIn) {
+ addVariable(new Variable(strName, objIn, Variable.NUMBER));
+ }
+
+ public void addVariable(String strName, String objIn) {
+ addVariable(new Variable(strName, objIn, Variable.STRING));
+ }
+
+ public void addVariable(String strName, LivingThing objIn) {
+ addVariable(new Variable(strName, objIn, Variable.THING));
+ }
+
+ /*void addVariable(String strName, Item objIn)
+ {
+ if (strName.equalsIgnoreCase("name")
+ ||strName.equalsIgnoreCase("clan")
+ ||strName.equalsIgnoreCase("concat"))
+ {
+ // engGame.log.printMessage(Log.ERROR, "addVariable():You cannot create a variable with the name \""+strName+"\".");
+ return;
+ }
+ Variable varStore;
+ for (int i=0;i<vctVariables.size();i++)
+ {
+ varStore = (Variable)vctVariables.elementAt(i);
+ if (varStore.strName.equals(strName))
+ {
+ vctVariables.removeElementAt(i);
+ break;
+ }
+ }
+ varStore = new Variable();
+ varStore.strName = strName;
+ varStore.objData = objIn;
+ varStore.bytType = 3;
+ vctVariables.addElement(varStore);
+ }*/
+ public Variable getVariable(String strName) {
+ return vctVariables.get(strName.toLowerCase());
+ }
+
+ public void removeVariable(String strName) {
+ vctVariables.remove(strName.toLowerCase());
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server.entity;
+
+/**
+ * Base class for trained attributes.
+ *
+ * Training goes up to 100.
+ *
+ * FIXME: there's something major wrong with abilities!!
+ *
+ * @author notzed
+ */
+public class Ability {
+
+ private int ability;
+ public final String name;
+
+ public Ability(String name) {
+ this.name = name;
+ }
+
+ public Ability(int ability, String name) {
+ ability = Math.max(ability, 0);
+ ability = Math.min(ability, 100);
+ this.ability = ability;
+ this.name = name;
+ }
+
+ public void setAbility(int ability) {
+ ability = Math.max(ability, 0);
+ ability = Math.min(ability, 100);
+ this.ability = ability;
+ }
+
+ /**
+ * Train an ability.
+ *
+ * @param delta
+ * @return true if the ability was increased, false if it is already at maximum
+ */
+ public boolean train(int delta) {
+ if (ability < 100) {
+ setAbility(ability + delta);
+ return true;
+ }
+ return false;
+ }
+
+ public int getAbility() {
+ return ability;
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - modernised java, added list functions and
+ * serialisation..
+ */
+package duskz.server.entity;
+
+import duskz.protocol.MessageType;
+import duskz.protocol.ServerMessage;
+import duskz.protocol.ServerMessage.EntityMessage;
+
+/*
+ All code copyright Tom Weingarten (captaint@home.com) 2000
+ Tom Weingarten makes no assurances as to the reliability or
+ functionality of this code. Use at your own risk.
+
+ You are free to edit or redistribute this code or any portion
+ at your wish, under the condition that you do not edit or
+ remove this license, and accompany it with all redistributions.
+ */
+/**
+ * DuskObject is the basic type of entity in Dusk.
+ *
+ * @author Tom Weingarten
+ */
+public abstract class DuskObject {
+
+ public static final byte LIVING_THING = 0;
+ public static final byte ITEM = 1;
+ public static final byte PROP = 2;
+ public static final byte SIGN = 3;
+ public static final byte MERCHANT = 4;
+ public static final byte PLAYER_MARCHANT = 5;
+ final public long ID; // Unique ID if this object
+ public String name; // Name of this object
+ public String description = null; // Description of this object
+ boolean isHideName; // if true: Do not display object's name on the client map.
+ public int x, y;
+ DuskObject next = null; //Linked List
+
+ public DuskObject(long ID, String name) {
+ this.ID = ID;
+ this.name = name;
+ }
+
+ public DuskObject(byte bytObjType, long ID) {
+ this.ID = ID;
+ }
+
+ public abstract byte getType();
+
+ public abstract int getImage();
+ // for some fucked reason this doesn't match getType()
+
+ public abstract int getEntityType();
+
+ // These are a bit dumb - we have objects to change behaviour.
+ public boolean isLivingThing() {
+ return getType() == LIVING_THING;
+ }
+
+ public boolean isItem() {
+ return getType() == ITEM;
+ }
+
+ public boolean isProp() {
+ return getType() == PROP;
+ }
+
+ public boolean isSign() {
+ return getType() == SIGN;
+ }
+
+ public boolean isMerchant() {
+ return getType() == MERCHANT;
+ }
+
+ public boolean isPlayerMerchant() {
+ return getType() == PLAYER_MARCHANT;
+ }
+
+ public long getID() {
+ return ID;
+ }
+
+ /**
+ * Convert to on-wire entity format
+ *
+ * @param eng
+ * @return
+ */
+ public String toEntity() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append(name).append('\n');
+ sb.append(getEntityType()).append('\n');
+ sb.append(ID).append('\n');
+ sb.append(x).append('\n');
+ sb.append(y).append('\n');
+ sb.append(getImage()).append('\n');
+
+ return sb.toString();
+ }
+
+ public EntityMessage toMessage(MessageType type) {
+ return new ServerMessage.EntityMessage(type, ID, name,
+ (byte) getEntityType(), (short) x, (short) y, (short) getImage(), (short) -1);
+ }
+
+ // Linked list stuff - should it just use a container?
+ public DuskObject getNext() {
+ return next;
+ }
+
+ /**
+ * Measure the distance between two objects.
+ *
+ * @param o Other object
+ * @return integer version of Euclidian distance.
+ */
+ public int distance(DuskObject o) {
+ int dx = o.x - x;
+ int dy = o.y - y;
+
+ return (int) Math.sqrt(dx * dx + dy * dy);
+ }
+
+ /**
+ * Measure the number of tile steps to get to the target. Just uses
+ * "Manhatten" distance.
+ *
+ * @param o
+ * @return
+ */
+ public int tileDistance(DuskObject o) {
+ return Math.abs(o.x - x) + Math.abs(o.y - y);
+ }
+
+ /**
+ * Calculate if this object is 1 block away in any cardinal direction
+ *
+ * @param o
+ * @return
+ */
+ public boolean adjacent(DuskObject o) {
+ return Math.abs(o.x - x) + Math.abs(o.y - y) <= 1;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getName() + " '" + name + "' @ " + x + "," + y;
+ }
+
+ @Deprecated
+ public static DuskObject find(DuskObject o, String name) {
+ while (o != null) {
+ if (o.name.equalsIgnoreCase(name)) {
+ break;
+ }
+ o = o.next;
+ }
+ return o;
+ }
+
+ /**
+ * append o to the end of the bucket chain from root
+ *
+ * @param root
+ * @param o
+ * @return if root is null then o, otherwise root
+ */
+ public static DuskObject append(DuskObject root, DuskObject o) {
+ if (o == root) {
+ return root;
+ }
+
+ if (root == null) {
+ o.next = null;
+ return o;
+ }
+
+ DuskObject d = root;
+ while (d.next != null) {
+ if (d == o) {
+ return root;
+ }
+ d = d.next;
+ }
+ o.next = null;
+ d.next = o;
+
+ return root;
+ }
+
+ /**
+ * Remove o from a chain from root, returns new root
+ *
+ * @param root
+ * @param o
+ * @return
+ */
+ public static DuskObject remove(DuskObject root, DuskObject o) {
+ if (root == null) {
+ return null;
+ } else if (root == o) {
+ DuskObject n = o.next;
+ o.next = null;
+ return n;
+ } else {
+ DuskObject d = root;
+ while (d.next != null) {
+ if (d.next == o) {
+ d.next = o.next;
+ o.next = null;
+ break;
+ }
+ d = d.next;
+ }
+ return root;
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - modernised java, big refactor.
+ */
+package duskz.server.entity;
+
+import duskz.protocol.Wearing;
+
+/**
+ * Equipment contains all the Items a LivingThing is wearing.
+ *
+ * @author Tom Weingarten
+ */
+public class Equipment implements Wearing {
+
+ // Must match Wearing
+ public static final String[] USER_NAMES = {
+ "wield2", "arms2", "legs2", "torso2", "waist2", "neck2", "skull2", "eyes2", "hands2"
+ };
+ public static final float[] ARMOUR_MOD = {
+ 0f, 0.05f, 0.05f, 0.40f, 0.15f, 0.05f, 0.20f, 0.05f, 0.05f
+ };
+ private Item[] worn = new Item[WEARING_COUNT];
+
+ /**
+ * Encode for network.
+ *
+ * @return
+ */
+ public String toEntity() {
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < worn.length; i++) {
+ Item item = worn[i];
+ if (item != null)
+ sb.append(item.name).append('\n');
+ else
+ sb.append("none\n");
+ }
+ return sb.toString();
+ }
+
+ public Item getWorn(int where) {
+ return worn[where];
+ }
+
+ public boolean isWearing(String what) {
+ for (Item item : worn) {
+ if (item != null && what.equalsIgnoreCase(item.name))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Where a sepecific item
+ *
+ * @param where
+ * @param item
+ * @return
+ */
+ public Item wear(int where, Item item) {
+ Item old = worn[where];
+
+ worn[where] = item;
+ return old;
+ }
+
+ /**
+ * Unwear item at specific location
+ *
+ * @param where
+ * @return item if worn
+ */
+ public Item unwear(int where) {
+ Item old = worn[where];
+
+ worn[where] = null;
+ return old;
+ }
+
+ /**
+ * Unwear an item of a sepcific name
+ *
+ * @param name
+ * @return item if worn
+ */
+ public Item unwearByName(String name) {
+ for (int i = 0; i < worn.length; i++) {
+ Item item = worn[i];
+
+ if (item != null && name.equalsIgnoreCase(item.name)) {
+ worn[i] = null;
+ return item;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Convert to wield type index
+ *
+ * @param where
+ * @return
+ */
+ public static int toIndex(String where) {
+ switch (where.toLowerCase()) {
+ case "wielded":
+ return WIELD;
+ case "arms":
+ return ARMS;
+ case "legs":
+ return LEGS;
+ case "torso":
+ return TORSO;
+ case "waist":
+ return WAIST;
+ case "neck":
+ return NECK;
+ case "skull":
+ return SKULL;
+ case "eyes":
+ return EYES;
+ case "hands":
+ return HANDS;
+ }
+ return -1;
+ }
+
+ public int armourCount() {
+ int count = 0;
+ for (int i = ARMS; i < worn.length; i++) {
+ if (worn[i] != null)
+ count++;
+ }
+ return count;
+ }
+
+ public int armourMod() {
+ int mod = 0;
+
+ for (int i = 0; i < worn.length; i++) {
+ Item item = worn[i];
+
+ if (item != null) {
+ mod += ARMOUR_MOD[i] * item.intMod;
+ }
+ }
+ return mod;
+ }
+
+ /**
+ * Damage the specified item if it exists
+ *
+ * @param damage
+ * @return the weapon if it was destroyed
+ */
+ public Item damageItem(int index, int damage) {
+ Item item = worn[index];
+
+ if (item != null && item.lngDurability != -1) {
+ item.lngDurability -= damage;
+ if (item.lngDurability < 0) {
+ worn[index] = null;
+ return item;
+ }
+ }
+ return null;
+ }
+ // TODO: load/save functions here too?
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - modernised java, factory method/loader and script
+ * wrappers.
+ */
+package duskz.server.entity;
+
+import duskz.server.DuskEngine;
+import duskz.server.Script;
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/*
+ All code copyright Tom Weingarten (captaint@home.com) 2000
+ Tom Weingarten makes no assurances as to the reliability or
+ functionality of this code. Use at your own risk.
+
+ You are free to edit or redistribute this code or any portion
+ at your wish, under the condition that you do not edit or
+ remove this license, and accompany it with all redistributions.
+ */
+//0-Ordinary Item
+//1-Weapon
+//2-Armor
+//3-Food
+//4-Drink
+/**
+ * An Item is an object that can be picked up, worn, and used. It can be of type
+ * Ordinary Item, Weapon, Armor, Food, or Drink.
+ *
+ * @author Tom Weingarten
+ */
+public class Item extends DuskObject {
+
+ public static final int ORDINARY = 0;
+ public static final int WEAPON = 1;
+ public static final int ARMOR = 2;
+ public static final int FOOD = 3;
+ public static final int DRINK = 4;
+ public static final int CONTAINER = 5;
+ private String strOnGetScript = null,
+ strOnDropScript = null;
+ public String strOnUseScript = null,
+ strOnWearScript = null,
+ strOnUnWearScript = null,
+ strOnOpenScript = null,
+ strOnCloseScript = null,
+ strOnAddItemScript = null,
+ strOnRemoveItemScript = null;
+ public int intCost,
+ intType = -1,
+ intKind = -1,
+ intMod,
+ intUses = -1,
+ intRange = 1;
+ int intImage;
+ int intWeight; // How much this object weighs
+ int intSize; // Amount of space this object takes up
+ int intCapacity; // How many items can this container hold
+ int intWeightLimit; // How much weight can this container hold
+ public long lngDurability = -1;
+ Item itmNext = null;
+
+ public Item(long lngID, String name) {
+ super(lngID, name);
+ }
+
+ boolean isOrdinaryItem() {
+ if (intType == ORDINARY) {
+ return true;
+ }
+ return false;
+ }
+
+ boolean isWeapon() {
+ if (intType == WEAPON) {
+ return true;
+ }
+ return false;
+ }
+
+ boolean isArmor() {
+ if (intType == ARMOR) {
+ return true;
+ }
+ return false;
+ }
+
+ boolean isFood() {
+ if (intType == FOOD) {
+ return true;
+ }
+ return false;
+ }
+
+ boolean isDrink() {
+ if (intType == DRINK) {
+ return true;
+ }
+ return false;
+ }
+
+ boolean isContainer() {
+ if (intType == CONTAINER) {
+ return true;
+ }
+ return false;
+ }
+
+ int range() {
+ return intRange;
+ }
+
+ @Override
+ public int getImage() {
+ return intImage;
+ }
+
+ @Override
+ public byte getType() {
+ return ITEM;
+ }
+
+ @Override
+ public int getEntityType() {
+ return 1;
+ }
+
+ /*
+ ** This method formats the Item for saving.
+ ** It generates a String that can later be passed
+ ** to fromString for populating a new Item.
+ */
+ public String toString() {
+ return "[strName:" + name
+ + "::strDescription:" + description
+ + "::strOnUseScript:" + strOnUseScript
+ + "::strOnWearScript:" + strOnWearScript
+ + "::strOnUnWearScript:" + strOnUnWearScript
+ + "::strOnGetScript:" + strOnGetScript
+ + "::strOnDropScript:" + strOnDropScript
+ + "::intCost:" + intCost
+ + "::intType:" + intType
+ + "::intKind:" + intKind
+ + "::intMod:" + intMod
+ + "::intImage:" + intImage
+ + "::intUses:" + intUses
+ + "::intRange:" + intRange
+ + "::lngDurability:" + lngDurability
+ + "]";
+ }
+
+ public static Item getItem(long id, String inName) throws IOException {
+ Item itmStore = null;
+ RandomAccessFile rafItemDef = null;
+ String strStore = "Error reading file";
+ try {
+ File fileTest = new File("defItems/" + inName.toLowerCase());
+ if (!fileTest.exists()) {
+ return null;
+ }
+ rafItemDef = new RandomAccessFile("defItems/" + inName.toLowerCase(), "r");
+ //itmStore = new Item(this);
+ itmStore = new Item(id, inName);
+ itmStore.description = "a " + inName; //default description is name
+ strStore = rafItemDef.readLine();
+ while (!(strStore == null || strStore.equals("."))) {
+ // FIXME: use enums
+ if (strStore.equalsIgnoreCase("type")) {
+ strStore = rafItemDef.readLine();
+ if (strStore.equalsIgnoreCase("item")) {
+ itmStore.intType = 0;
+ } else if (strStore.equalsIgnoreCase("weapon")) {
+ itmStore.intType = 1;
+ } else if (strStore.equalsIgnoreCase("armor")) {
+ itmStore.intType = 2;
+ } else if (strStore.equalsIgnoreCase("food")) {
+ itmStore.intType = 3;
+ } else if (strStore.equalsIgnoreCase("drink")) {
+ itmStore.intType = 4;
+ }
+ } else if (strStore.equalsIgnoreCase("kind")) {
+ strStore = rafItemDef.readLine();
+ if (strStore.equalsIgnoreCase("arms")) {
+ itmStore.intKind = 0;
+ } else if (strStore.equalsIgnoreCase("legs")) {
+ itmStore.intKind = 1;
+ } else if (strStore.equalsIgnoreCase("torso")) {
+ itmStore.intKind = 2;
+ } else if (strStore.equalsIgnoreCase("waist")) {
+ itmStore.intKind = 3;
+ } else if (strStore.equalsIgnoreCase("neck")) {
+ itmStore.intKind = 4;
+ } else if (strStore.equalsIgnoreCase("skull")) {
+ itmStore.intKind = 5;
+ } else if (strStore.equalsIgnoreCase("eyes")) {
+ itmStore.intKind = 6;
+ } else if (strStore.equalsIgnoreCase("hands")) {
+ itmStore.intKind = 7;
+ }
+ } else if (strStore.equalsIgnoreCase("description")) {
+ itmStore.description = rafItemDef.readLine();
+ } else if (strStore.equalsIgnoreCase("cost")) {
+ itmStore.intCost = Integer.parseInt(rafItemDef.readLine());
+ } else if (strStore.equalsIgnoreCase("durability")) {
+ itmStore.lngDurability = Long.parseLong(rafItemDef.readLine());
+ } else if (strStore.equalsIgnoreCase("uses")) {
+ itmStore.intUses = Integer.parseInt(rafItemDef.readLine());
+ } else if (strStore.equalsIgnoreCase("mod")) {
+ itmStore.intMod = Integer.parseInt(rafItemDef.readLine());
+ } else if (strStore.equalsIgnoreCase("range")) {
+ itmStore.intRange = Integer.parseInt(rafItemDef.readLine());
+ } else if (strStore.equalsIgnoreCase("image")) {
+ itmStore.intImage = Integer.parseInt(rafItemDef.readLine());
+ } else if (strStore.equalsIgnoreCase("onuse")) {
+ itmStore.strOnUseScript = rafItemDef.readLine();
+ } else if (strStore.equalsIgnoreCase("onwear")) {
+ itmStore.strOnWearScript = rafItemDef.readLine();
+ } else if (strStore.equalsIgnoreCase("onunwear")) {
+ itmStore.strOnUnWearScript = rafItemDef.readLine();
+ } else if (strStore.equalsIgnoreCase("onget")) {
+ itmStore.strOnGetScript = rafItemDef.readLine();
+ } else if (strStore.equalsIgnoreCase("ondrop")) {
+ itmStore.strOnDropScript = rafItemDef.readLine();
+ }
+ strStore = rafItemDef.readLine();
+ }
+ } catch (NumberFormatException ex) {
+ throw new IOException("Parsing: " + strStore, ex);
+ } catch (NullPointerException ex) {
+ throw new IOException(ex);
+ } finally {
+ if (rafItemDef != null) {
+ rafItemDef.close();
+ }
+ }
+ return itmStore;
+ }
+
+ public void onGetItem(DuskEngine eng, LivingThing trigger) {
+ if (strOnGetScript != null) {
+ try {
+ Script script = new Script("scripts/" + strOnGetScript, eng, false);
+ script.varVariables.addVariable("trigger", trigger);
+ script.varVariables.addVariable("itemname", name);
+ script.varVariables.addVariable("mod", intMod);
+ script.runScript();
+ script.close();
+ } catch (Exception e) {
+ eng.log.printError("While running onGet script(" + strOnGetScript + ") for item \"" + name + "\"", e);
+ }
+ }
+ }
+
+ public void onDropItem(DuskEngine eng, LivingThing trigger) {
+ if (strOnDropScript != null) {
+ try {
+ Script script = new Script("scripts/" + strOnDropScript, eng, false);
+ script.varVariables.clearVariables();
+ script.varVariables.addVariable("trigger", trigger);
+ script.varVariables.addVariable("itemname", name);
+ script.varVariables.addVariable("mod", intMod);
+ script.runScript();
+ script.close();
+ } catch (Exception e) {
+ eng.log.printError("While running onDrop script(" + strOnDropScript + ") for item \"" + name + "\"", e);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - modernised java, lots of clean up and encapsulation
+ * and synchronisation fixes. Moved loader here.
+ */
+package duskz.server.entity;
+
+import duskz.server.Battle;
+import duskz.server.Commands;
+import duskz.server.Condition;
+import duskz.server.DuskEngine;
+import duskz.server.ItemList;
+import duskz.server.Log;
+import duskz.protocol.MessageType;
+import duskz.server.Script;
+import duskz.server.SpellGroup;
+import duskz.server.Variable;
+import duskz.server.entity.TileMap.MapData;
+import duskz.server.entity.TileMap.MoveData;
+import duskz.protocol.ServerMessage;
+import java.io.*;
+import java.net.Socket;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * LivingThing defines the base class for all moving objects. This includes
+ * Players, Pets, and Mobs.
+ *
+ * @author Tom Weingarten
+ */
+public class LivingThing extends DuskObject implements Runnable {
+
+ DuskEngine game;
+ final public LinkedBlockingQueue<ServerMessage> messageQueue = new LinkedBlockingQueue<>();
+ //StillWorking?
+ public boolean isWorking = true;
+ //Has the player finished loading yet?
+ public boolean isLoaded = false;
+ //Should the player be in who yet?
+ public boolean isReady = false;
+ //Can we save the player yet?
+ public boolean isSaveable = false;
+ //SHOULD we save the player yet?
+ public boolean isSaveNeeded = false;
+ //Is player in process of closing?
+ public boolean isClosing = false;
+ //Should we stop the thread?
+ public boolean isStopped = false;
+ //Should we process in-game commands after script is finished?
+ //(The script can change this to false to stop it from happening)
+ //(This allows scripts to short-circuit in-game commands)
+ public boolean isAlwaysCommands = true;
+ // File names for i/o
+ File file, backup;
+ //ID data
+ public String password,
+ clan = "none",
+ title = null,
+ masterName = null;
+ //Group
+ LivingThing following = null,
+ master = null,
+ charmer = null;
+ //Stats
+ public int playerID, // uniquely identifies player for land ownership
+ hp,
+ maxhp,
+ mp,
+ maxmp,
+ originalX,
+ originalY,
+ stre,
+ inte,
+ dext,
+ cons,
+ wisd,
+ exp,
+ hpbon = 0,
+ mpbon = 0,
+ strebon = 0,
+ intebon = 0,
+ dextbon = 0,
+ consbon = 0,
+ wisdbon = 0,
+ dammodbon = 0,
+ rangebon = 0,
+ acbon = 0;
+ //Max values for stats
+ public int hp_limit = -1,
+ mp_limit = -1,
+ exp_limit = -1,
+ stre_limit = 100,
+ inte_limit = 100,
+ dext_limit = 100,
+ cons_limit = 100,
+ wisd_limit = 100;
+ // FIXME: not public
+ public long cash;
+ // FIXME: not public
+ public long lastMessageStamp = 0;
+ //Status
+ // FIXME: accessor
+ public boolean isSleeping;
+ //Is this livingthing currently allowed to move?
+ public boolean isMoveable = true;
+ //For commands that need input...
+ boolean isHalted = false;
+ //Battle
+ // FIXME: accessor
+ public Battle battle = null;
+ public byte battleSide;
+ public long damageDone;
+ //Flags
+ // FIXME: accessor/helper
+ final public List<String> flags = new LinkedList<>();
+ //Conditions
+ final public List<Condition> conditions = new ArrayList<>();
+ //Skills
+ final HashMap<String, Ability> skillMap = new HashMap<>(2);
+ //Spells
+ final HashMap<String, Ability> spellMap = new HashMap<>(2);
+ // worn, FIXME: not public
+ public Equipment wornItems;
+ //Items
+ public ItemList itemList;
+ //Movement queue
+ final private LinkedList<String> moveQueue = new LinkedList<>();
+ //Entities (for optimized refresh)
+ private final HashMap<Long, DuskObject> nearEntities = new HashMap<>();
+ //Image id
+ int imageid;
+ // Image step for animation selection
+ public int imagestep;
+ //Race
+ public String race = null;
+ //Priveleges
+ public int privs = 0;
+ //Socket connection
+ private Socket socket;
+ // FIXME: not public
+ public DataInputStream instream;
+ // FIXME: not public
+ public DataOutputStream outstream;
+ public Thread connectionThread;
+ private SendThread sendThread;
+ //Prefs
+ public boolean audioon = true,
+ coloron = true,
+ popup = true,
+ highlight = true,
+ noFollow = false;
+ public int noChannel = 0;
+ //Timestamp of last save
+ long lastSaveStamp;
+ //List of players being ignored
+ final public List<String> ignoreList = new ArrayList<>();
+ //Type
+ /*
+ 0=Player
+ 1=Mob
+ 2=Pet
+ */
+ byte Type;
+
+ public boolean isPlayer() {
+ if (Type == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isMob() {
+ if (Type == 1) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isPet() {
+ if (Type == 2) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public byte getType() {
+ return LIVING_THING;
+ }
+
+ @Override
+ public int getImage() {
+ return imageid;
+ }
+
+ @Override
+ public int getEntityType() {
+ if (isMob() || isPet()) {
+ return 4;
+ }
+ return 0;
+ }
+
+ /**
+ * Get IP address of user
+ *
+ * @return
+ */
+ public String getAddress() {
+ if (socket != null
+ && socket.isConnected())
+ return socket.getInetAddress().toString();
+ else
+ return null;
+ }
+
+ @Override
+ public String toEntity() {
+ StringBuilder sb = new StringBuilder();
+ if (isSleeping) {
+ sb.append("<sleeping>");
+ }
+ if (isPlayer() && !clan.equals("none")) {
+ sb.append('<');
+ sb.append(clan);
+ sb.append('>');
+ }
+ if (isPet() && hp < 0) {
+ sb.append("<wounded>");
+ }
+ for (String s : flags) {
+ sb.append('<');
+ sb.append(s);
+ sb.append('>');
+ }
+ sb.append(name).append('\n');
+ sb.append(getEntityType()).append('\n');
+ sb.append(ID).append('\n');
+ sb.append(x).append('\n');
+ sb.append(y).append('\n');
+ sb.append(getImage()).append('\n');
+ if (isPlayer()) {
+ sb.append(imagestep).append('\n');
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public ServerMessage.EntityMessage toMessage(MessageType type) {
+ StringBuilder sb = new StringBuilder();
+ if (isSleeping) {
+ sb.append("<sleeping>");
+ }
+ if (isPlayer() && !clan.equals("none")) {
+ sb.append('<');
+ sb.append(clan);
+ sb.append('>');
+ }
+ if (isPet() && hp < 0) {
+ sb.append("<wounded>");
+ }
+ for (String s : flags) {
+ sb.append('<');
+ sb.append(s);
+ sb.append('>');
+ }
+ sb.append(name);
+ return new ServerMessage.EntityMessage(type, ID, sb.toString(),
+ (byte) getEntityType(), (short) x, (short) y, (short) getImage(), (short) (isPlayer() ? imagestep : -1));
+ }
+
+ /**
+ * for extended classes
+ */
+ public LivingThing(long ID, String name) {
+ super(ID, name);
+ }
+
+ /**
+ * new Player
+ */
+ public LivingThing(Socket inSocket, DuskEngine inEngine) {
+ super(LIVING_THING, inEngine.getID());
+ try {
+ sendThread = new SendThread();
+ sendThread.start();
+ Type = 0;
+ game = inEngine;
+ socket = inSocket;
+ socket.setSoTimeout(600000); //10 minute timeout
+ socket.setSoLinger(false, 0); //Do not linger on disconnect
+ instream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
+ outstream = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
+ game.log.printMessage(Log.INFO, socket.toString());
+ battle = null;
+ isSleeping = false;
+
+ //
+ // WTF is this stuff doing here??
+
+ if (game.maxconnections != 0 && game.playersByName.size() >= game.maxconnections) {
+ chatMessage("Sorry, the server has reached it's connection limit. Try again later.");
+ send("Goodbye.\n" + (char) 0);
+ Thread.sleep(1000);
+ closeNosavePlayer();
+ return;
+ }
+ // Game is shutting down
+ if (game.blnShuttingDown) {
+ chatMessage("Sorry, the server is not accepting new connections. It is either being shutdown or worked on. Try again later.");
+ send("Goodbye.\n" + (char) 0);
+ Thread.sleep(1000);
+ closeNosavePlayer();
+ return;
+ }
+ if (!game.isGoodIP(socket.getInetAddress().toString())) {
+ chatMessage("Connections from your machine are no longer being accepted.");
+ send("Goodbye.\n" + (char) 0);
+ Thread.sleep(1000);
+ closeNosavePlayer();
+ return;
+ }
+ // IP Filter FIXME: put on engine
+ if (game.blnIPF) {
+ for (LivingThing lt : game.playersByName.values()) {
+ String IP = lt.socket.getInetAddress().toString();
+ if (IP.equalsIgnoreCase(socket.getInetAddress().toString())) {
+ chatMessage("There's already a player connected from your IP address.");
+ send("Goodbye.\n" + (char) 0);
+ Thread.sleep(1000);
+ closeNosavePlayer();
+ return;
+ }
+ }
+ }
+ // End IPF
+ } catch (Exception e) {
+ game.log.printError("LivingThing():Creating player", e);
+ }
+ }
+
+ /**
+ * new Pet
+ */
+ public LivingThing(String strName, String strType, LivingThing master, DuskEngine inEngine) {
+ super(inEngine.getID(), strName);
+ try {
+ Type = 2;
+ game = inEngine;
+ this.master = master;
+ masterName = this.master.name.toLowerCase();
+ charmer = this.master;
+ x = this.master.x;
+ y = this.master.y;
+ battle = null;
+ isSleeping = false;
+ wornItems = new Equipment();
+ itemList = new ItemList();
+
+ //Load pet files
+
+ String strStore = "";
+ if (strType != null) {
+ race = strType;
+ }
+ /*
+ ** check to see if a pet exists
+ */
+ File filCheck;
+ if (strName.equalsIgnoreCase("default")) {
+ strStore = this.master.name.toLowerCase();
+ filCheck = new File("pets/" + strStore);
+ if (!filCheck.exists() && strType == null) {
+ closeNosavePlayer();
+ return;
+ }
+ }
+ loadUserFile(new File("pets/default"));
+ strStore = this.master.name.toLowerCase();
+ File filPlayer = new File("pets/" + strStore);
+ File filBackup = new File("pets/" + strStore + ".backup");
+ /*
+ ** Check for old style pet name
+ ** (Only need to check if we already have a valid pet name)
+ */
+ if (!strName.equalsIgnoreCase("default")) {
+ strStore = strName.toLowerCase();
+ File filOldPet = new File("pets/" + strStore);
+ File filOldBackup = new File("pets/" + strStore + ".backup");
+ if (filOldPet.exists() && !filPlayer.exists()) {
+ filOldPet.renameTo(filPlayer);
+ filOldPet.delete();
+ }
+ if (filOldBackup.exists() && !filBackup.exists()) {
+ filOldBackup.renameTo(filBackup);
+ filOldBackup.delete();
+ }
+ }
+ strStore = this.master.name.toLowerCase();
+ int i = 0;
+ if (filBackup.exists()) {
+ if (filPlayer.length() > filBackup.length()) {
+ filCheck = new File("backup/" + strStore + ".possiblyDamaged");
+ while (filCheck.exists()) {
+ i++;
+ filCheck = new File("backup/" + strStore + ".possiblyDamaged." + i);
+ }
+ filBackup.renameTo(filCheck);
+ } else if (filPlayer.length() < filBackup.length()) {
+ filCheck = new File("backup/" + strStore + ".possiblyDamaged");
+ while (filCheck.exists()) {
+ i++;
+ filCheck = new File("backup/" + strStore + ".possiblyDamaged." + i);
+ }
+ filPlayer.renameTo(filCheck);
+ filBackup.renameTo(new File("pets/" + strStore));
+ }
+ }
+ strStore = this.master.name.toLowerCase();
+
+ file = new File("pets", strStore);
+ backup = new File("pets", strStore + ".backup");
+ loadUserFile(file);
+ if (race != null) {
+ loadRaceFile(new File("defPets/" + race.toLowerCase()), true);
+ }
+ if (masterName == null) {
+ masterName = this.master.name.toLowerCase();
+ }
+ //game.vctPets.addElement(this);
+ isSaveable = true;
+ } catch (Exception e) {
+ game.log.printError("LivingThing():Creating pet", e);
+ close();
+ }
+ }
+
+ public LivingThing getFollowing() {
+ return following;
+ }
+
+ public LivingThing getMaster() {
+ return master;
+ }
+
+ public LivingThing getCharmer() {
+ return charmer;
+ }
+
+ public void setFollowing(LivingThing following) {
+ this.following = following;
+ }
+
+ public void setMaster(LivingThing master) {
+ this.master = master;
+ }
+
+ public void leaveBattle() {
+ battle = null;
+ battleSide = 0;
+ isMoveable = true;
+ }
+
+ public void enterBattle(Battle battle, int sideid) {
+// thnAdded.changeLocBypass(thnFront1.intLocX,thnFront1.intLocY);
+ isMoveable = false;
+ isSleeping = false;
+ this.battle = battle;
+ updateActions();
+ battleSide = (byte) sideid;
+ }
+
+ private void setAbility(Map<String, Ability> map, String name, int value) {
+ map.put(name.toLowerCase(), new Ability(value, name));
+ }
+
+ private int getAbility(Map<String, Ability> map, String name) {
+ Ability ability = map.get(name.toLowerCase());
+
+ return ability != null ? ability.getAbility() : 0;
+ }
+
+ public int getSkill(String name) {
+ return getAbility(skillMap, name);
+ }
+
+ public int getSpell(String name) {
+ return getAbility(spellMap, name);
+ }
+
+ /**
+ * Train a skill or spell.
+ *
+ * @param name
+ * @param add increment
+ * @return true if the skill/spell exists and was created/incremented
+ */
+ public boolean addToSkill(String name, int add) {
+ System.out.println("adding to skill " + name + " " + add);
+ String key = name.toLowerCase();
+ try {
+ Ability skill = spellMap.get(key);
+ if (skill == null) {
+ File filCheck = new File("defSpellGroups/" + name);
+ if (filCheck.exists()) {
+ setAbility(spellMap, name, add);
+ return true;
+ }
+ if ((skill = skillMap.get(name)) == null) {
+ setAbility(skillMap, name, add);
+ return true;
+ }
+ }
+ return skill.train(add);
+ } catch (Exception e) {
+ game.log.printError("addToSkill()", e);
+ }
+ return false;
+ }
+
+ public boolean setSkill(String name, int value) {
+ String key = name.toLowerCase();
+ if (value <= 0) {
+ if (skillMap.remove(key) != null) {
+ return true;
+ }
+ if (spellMap.remove(key) != null) {
+ return true;
+ }
+ return false;
+ }
+ // TODO: try/catch not needed here
+ try {
+
+ Ability skill = spellMap.get(key);
+ if (skill == null) {
+ File filCheck = new File("defSpellGroups/" + name);
+ if (filCheck.exists()) {
+ setAbility(spellMap, name, value);
+ return true;
+ }
+ if ((skill = skillMap.get(name)) == null) {
+ setAbility(skillMap, name, value);
+ return true;
+ }
+ }
+ skill.setAbility(value);
+ return true;
+ } catch (Exception e) {
+ game.log.printError("setSkill()", e);
+ }
+ return false;
+ }
+
+ int totalSkillValue() {
+ int total = 0;
+
+ for (Ability skill : skillMap.values())
+ total += skill.getAbility();
+ for (Ability spell : spellMap.values())
+ total += spell.getAbility();
+ return total;
+ }
+
+ public void loadUserFile(File path) throws FileNotFoundException, IOException {
+ String line;
+ try (RandomAccessFile file = new RandomAccessFile(path, "r")) {
+ while (!((line = file.readLine()) == null || line.equals("."))) {
+ try {
+ parseUserFile(file, line);
+ } catch (NumberFormatException x) {
+ throw new IOException("Problem parsing user " + path + " on field " + line, x);
+ }
+ }
+ }
+ }
+
+ protected void parseWear(RandomAccessFile in, int where) throws IOException {
+ Item item = game.getItem(in.readLine());
+ if (item != null) {
+ item.lngDurability = Long.parseLong(in.readLine());
+ item.intUses = Integer.parseInt(in.readLine());
+ wornItems.wear(where, item);
+ onWear(item);
+ }
+ }
+
+ protected void parseUserFile(RandomAccessFile in, String type) throws IOException, NumberFormatException {
+ switch (type.toLowerCase()) {
+ case "timestamp":
+ lastSaveStamp = Long.parseLong(in.readLine());
+ break;
+ case "petname":
+ name = in.readLine();
+ break;
+ case "master":
+ masterName = in.readLine();
+ break;
+ case "skill":
+ type = in.readLine();
+ addToSkill(type, Byte.parseByte(in.readLine()));
+ break;
+ case "condition": {
+ // FIXME: i/o to Condition
+ Condition cndStore = game.getCondition(in.readLine());
+ cndStore.ticksPast = Integer.parseInt(in.readLine());
+ cndStore.duration = Integer.parseInt(in.readLine());
+ if (cndStore.duration < -1) { // only necessary to repair
+ cndStore.duration = -1; // after bug fix, can go away
+ }
+ addCondition(cndStore);
+ break;
+ }
+ case "item": {
+ Item itmStore = game.getItem(in.readLine());
+ if (itmStore != null) {
+ itemList.addElement(itmStore);
+ }
+ break;
+ }
+ case "item2": { //for compatibility. Will be replaced with item later
+ Item itmStore = game.getItem(in.readLine());
+ if (itmStore != null) {
+ itmStore.lngDurability = Long.parseLong(in.readLine());
+ itmStore.intUses = Integer.parseInt(in.readLine());
+ itemList.addElement(itmStore);
+ }
+ break;
+ }
+ case "privs":
+ privs = Byte.parseByte(in.readLine());
+ break;
+ case "clan":
+ clan = in.readLine();
+ break;
+ case "race":
+ race = in.readLine();
+ break;
+ case "title":
+ title = in.readLine();
+ break;
+ case "description":
+ description = in.readLine();
+ break;
+ case "x":
+ x = Integer.parseInt(in.readLine());
+ break;
+ case "y":
+ y = Integer.parseInt(in.readLine());
+ break;
+ case "hp":
+ hp = Integer.parseInt(in.readLine());
+ break;
+ case "maxhp":
+ maxhp = Integer.parseInt(in.readLine());
+ break;
+ case "mp":
+ case "sp":
+ mp = Integer.parseInt(in.readLine());
+ break;
+ case "maxmp":
+ case "maxsp":
+ maxmp = Integer.parseInt(in.readLine());
+ break;
+ case "cash":
+ cash = Integer.parseInt(in.readLine());
+ break;
+ case "exp":
+ exp = Integer.parseInt(in.readLine());
+ break;
+ case "stre":
+ stre = Integer.parseInt(in.readLine());
+ break;
+ case "inte":
+ inte = Integer.parseInt(in.readLine());
+ break;
+ case "dext":
+ dext = Integer.parseInt(in.readLine());
+ break;
+ case "cons":
+ cons = Integer.parseInt(in.readLine());
+ break;
+ case "wisd":
+ wisd = Integer.parseInt(in.readLine());
+ break;
+ case "image":
+ imageid = Integer.parseInt(in.readLine());
+ break;
+ case "pet":
+ if (!isPet()) {
+ following = new LivingThing(in.readLine(), null, this, game);
+ }
+ break;
+ // FIXME: do i need these 'old' versions?
+ case "wield":
+ wornItems.wear(Equipment.WIELD, game.getItem(in.readLine()));
+ break;
+ case "arms":
+ wornItems.wear(Equipment.ARMS, game.getItem(in.readLine()));
+ break;
+ case "legs":
+ wornItems.wear(Equipment.LEGS, game.getItem(in.readLine()));
+ break;
+ case "torso":
+ wornItems.wear(Equipment.TORSO, game.getItem(in.readLine()));
+ break;
+ case "waist":
+ wornItems.wear(Equipment.WAIST, game.getItem(in.readLine()));
+ break;
+ case "neck":
+ wornItems.wear(Equipment.NECK, game.getItem(in.readLine()));
+ break;
+ case "skull":
+ wornItems.wear(Equipment.SKULL, game.getItem(in.readLine()));
+ break;
+ case "eyes":
+ wornItems.wear(Equipment.EYES, game.getItem(in.readLine()));
+ break;
+ case "hands":
+ wornItems.wear(Equipment.HANDS, game.getItem(in.readLine()));
+ break;
+ case "wield2":
+ parseWear(in, Equipment.WIELD);
+ break;
+ case "arms2":
+ parseWear(in, Equipment.ARMS);
+ break;
+ case "legs2":
+ parseWear(in, Equipment.LEGS);
+ break;
+ case "torso2":
+ parseWear(in, Equipment.TORSO);
+ break;
+ case "waist2":
+ parseWear(in, Equipment.WAIST);
+ break;
+ case "neck2":
+ parseWear(in, Equipment.NECK);
+ break;
+ case "skull2":
+ parseWear(in, Equipment.SKULL);
+ break;
+ case "eyes2":
+ parseWear(in, Equipment.EYES);
+ break;
+ case "hands2":
+ parseWear(in, Equipment.HANDS);
+ break;
+ case "nofollow":
+ noFollow = true;
+ break;
+ case "nopopup":
+ popup = false;
+ break;
+ case "nochannel":
+ noChannel = Integer.parseInt(in.readLine());
+ break;
+ case "audiooff":
+ audioon = false;
+ break;
+ case "coloroff":
+ coloron = false;
+ break;
+ }
+ // engGame.log.printError("parseUserFile():Parsing \"" + strStore + "\" from " + name + "'s file", e);
+ }
+
+ public void loadRaceFile(File path, boolean add) throws FileNotFoundException, IOException {
+ String line;
+ try (RandomAccessFile file = new RandomAccessFile(path, "r")) {
+ while (!((line = file.readLine()) == null || line.equals("."))) {
+ try {
+ parseRaceFile(file, line, add);
+ } catch (NumberFormatException x) {
+ throw new IOException("Problem parsing race " + path + " on field " + line, x);
+ }
+ }
+ }
+ }
+
+ protected void parseRaceFile(RandomAccessFile file, String strStore, boolean add) {
+ int s = add ? 1 : -1;
+ try {
+ switch (strStore) {
+ case "hp":
+ hpbon += s * Integer.parseInt(file.readLine());
+ break;
+ case "mp":
+ mpbon += s * Integer.parseInt(file.readLine());
+ break;
+ case "stre":
+ strebon += s * Integer.parseInt(file.readLine());
+ break;
+ case "inte":
+ intebon += s * Integer.parseInt(file.readLine());
+ break;
+ case "dext":
+ dextbon += s * Integer.parseInt(file.readLine());
+ break;
+ case "cons":
+ consbon += s * Integer.parseInt(file.readLine());
+ break;
+ case "wisd":
+ wisdbon += s * Integer.parseInt(file.readLine());
+ break;
+ case "range":
+ rangebon += s * Integer.parseInt(file.readLine());
+ break;
+ case "hp_limit":
+ hp_limit = add ? Integer.parseInt(file.readLine()) : -1;
+ break;
+ case "mp_limit":
+ mp_limit = add ? Integer.parseInt(file.readLine()) : -1;
+ break;
+ case "exp_limit":
+ exp_limit = add ? Integer.parseInt(file.readLine()) : -1;
+ break;
+ case "stre_limit":
+ stre_limit = add ? Integer.parseInt(file.readLine()) : 100;
+ break;
+ case "inte_limit":
+ inte_limit = add ? Integer.parseInt(file.readLine()) : 100;
+
+ break;
+ case "dext_limit":
+ dext_limit = add ? Integer.parseInt(file.readLine()) : 100;
+ break;
+ case "cons_limit":
+ cons_limit = add ? Integer.parseInt(file.readLine()) : 100;
+ break;
+ case "wisd_limit":
+ wisd_limit = add ? Integer.parseInt(file.readLine()) : 100;
+ break;
+ case "image":
+ imageid = Integer.parseInt(file.readLine());
+ break;
+ }
+ } catch (Exception e) {
+ game.log.printError("parseRaceFile():Parsing \"" + strStore + "\" from " + name + "'s race file", e);
+ }
+ }
+
+ void writePlayerFile(RandomAccessFile rafPlayerFile) throws IOException {
+ synchronized (rafPlayerFile) {
+ rafPlayerFile.setLength(0);
+ if (isPlayer()) {
+ rafPlayerFile.writeBytes(password + "\n");
+ rafPlayerFile.writeBytes("privs\n" + String.valueOf(privs) + "\n");
+ if (title != null) {
+ rafPlayerFile.writeBytes("title\n" + title + "\n");
+ }
+ if (clan != null) {
+ rafPlayerFile.writeBytes("clan\n" + clan + "\n");
+ } else {
+ rafPlayerFile.writeBytes("clan\nnone\n");
+ }
+ rafPlayerFile.writeBytes("x\n" + String.valueOf(x) + "\n");
+ rafPlayerFile.writeBytes("y\n" + String.valueOf(y) + "\n");
+ if (popup == false) {
+ rafPlayerFile.writeBytes("nopopup\n");
+ }
+ if (audioon == false) {
+ rafPlayerFile.writeBytes("audiooff\n");
+ }
+ if (coloron == false) {
+ rafPlayerFile.writeBytes("coloroff\n");
+ }
+ if (noFollow == true) {
+ rafPlayerFile.writeBytes("nofollow\n");
+ }
+ if (noChannel != 0) {
+ rafPlayerFile.writeBytes("nochannel\n" + noChannel + "\n");
+ }
+ }
+ rafPlayerFile.writeBytes("race\n" + race + "\n");
+ if (isPet()) {
+ rafPlayerFile.writeBytes("petname\n" + name + "\n");
+ rafPlayerFile.writeBytes("master\n" + masterName + "\n");
+ }
+ if (description != null) {
+ rafPlayerFile.writeBytes("description\n" + description + "\n");
+ }
+ rafPlayerFile.writeBytes("exp\n" + String.valueOf(exp) + "\n");
+ rafPlayerFile.writeBytes("hp\n" + String.valueOf(hp) + "\n");
+ rafPlayerFile.writeBytes("maxhp\n" + String.valueOf(maxhp) + "\n");
+ rafPlayerFile.writeBytes("mp\n" + String.valueOf(mp) + "\n");
+ rafPlayerFile.writeBytes("maxmp\n" + String.valueOf(maxmp) + "\n");
+ rafPlayerFile.writeBytes("cash\n" + String.valueOf(cash) + "\n");
+ rafPlayerFile.writeBytes("stre\n" + String.valueOf(stre) + "\n");
+ rafPlayerFile.writeBytes("inte\n" + String.valueOf(inte) + "\n");
+ rafPlayerFile.writeBytes("dext\n" + String.valueOf(dext) + "\n");
+ rafPlayerFile.writeBytes("cons\n" + String.valueOf(cons) + "\n");
+ rafPlayerFile.writeBytes("wisd\n" + String.valueOf(wisd) + "\n");
+
+ for (Ability skill : skillMap.values())
+ rafPlayerFile.writeBytes("skill\n" + skill.name + "\n" + skill.getAbility() + "\n");
+ for (Ability spell : spellMap.values())
+ rafPlayerFile.writeBytes("skill\n" + spell.name + "\n" + spell.getAbility() + "\n");
+ for (Condition cond : conditions) {
+ rafPlayerFile.writeBytes("condition\n" + cond.name + "\n" + cond.ticksPast + "\n" + cond.duration + "\n");
+ }
+ for (int i = 0; i < Equipment.WEARING_COUNT; i++) {
+ Item item = wornItems.getWorn(i);
+ if (item != null) {
+ rafPlayerFile.writeBytes(Equipment.USER_NAMES[i] + "\n" + item.name + "\n" + item.lngDurability + "\n" + item.intUses + "\n");
+ }
+ }
+ for (LinkedList<Item> list : itemList.values()) {
+ for (Item item : list) {
+ rafPlayerFile.writeBytes("item2\n" + item.name + "\n" + item.lngDurability + "\n" + item.intUses + "\n");
+ }
+ }
+ rafPlayerFile.writeBytes(".\n");//end of file
+ }
+ }
+
+ public void savePlayer() {
+ if (!isSaveNeeded) {
+ /*
+ ** User info has not changed significantly
+ ** No need to save at this time.
+ */
+ return;
+ }
+ if (!isSaveable) {
+ /*
+ ** File is currently loading or saving and is not safe to
+ ** save at this time.
+ */
+ return;
+ }
+ isSaveable = false;
+
+ String strStore = name.toLowerCase();
+ String strDirName = "users";
+ if (isPet()) {
+ strStore = masterName;
+ strDirName = "pets";
+ }
+
+ // This should work if it's going to, write out a whole file,
+ // and if that succeeds, copy it over
+
+ try (RandomAccessFile rafFile = new RandomAccessFile(backup, "rw")) {
+ writePlayerFile(rafFile);
+ } catch (IOException x) {
+ game.log.printMessage(Log.ERROR, "savePlayer():Saving primary file for " + backup + ", failed, aborting savePlayer");
+ isSaveable = true;
+ return;
+ }
+
+ try {
+ Files.move(backup.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ } catch (IOException ex) {
+ game.log.printMessage(Log.ERROR, "savePlayer():Renaming primary file for " + file + ", failed, aborting savePlayer");
+ }
+
+ /*
+
+ boolean blnSaveSuccessful;
+ long lngFileLength = 0;
+ blnSaveSuccessful = writePlayerFile(rafFile);
+ try {
+ lngFileLength = rafFile.length();
+ } catch (Exception e) {
+ }
+
+ if (!blnSaveSuccessful || (lngFileLength < 100)) {
+ // Error saving file. Close it, open it back up, and try again.
+ try {
+ rafFile.close();
+ } catch (Exception e) {
+ }
+ try {
+ rafFile = new RandomAccessFile(strDirName + "/" + strStore, "rw");
+ } catch (Exception e) {
+ }
+
+ blnSaveSuccessful = writePlayerFile(rafFile);
+
+ try {
+ lngFileLength = rafFile.length();
+ } catch (Exception e) {
+ }
+
+ if (!blnSaveSuccessful || (lngFileLength < 100)) {
+ engGame.log.printMessage(Log.ERROR, "savePlayer():Saving primary file for " + name + ", second try failed, aborting savePlayer");
+ blnCanSave = true;
+ return;
+ }
+ }
+
+ blnShouldSave = false;
+
+ blnSaveSuccessful = writePlayerFile(rafBackup);
+
+ try {
+ lngFileLength = rafBackup.length();
+ } catch (Exception e) {
+ }
+
+ if (!blnSaveSuccessful || (lngFileLength < 100)) {
+ // Error saving file. Close it, open it back up, and try again.
+ try {
+ rafBackup.close();
+ } catch (Exception e) {
+ }
+ try {
+ rafBackup = new RandomAccessFile(strDirName + "/" + strStore + ".backup", "rw");
+ } catch (Exception e) {
+ }
+
+ blnSaveSuccessful = writePlayerFile(rafBackup);
+
+ try {
+ lngFileLength = rafBackup.length();
+ } catch (Exception e) {
+ }
+
+ if (!blnSaveSuccessful || (lngFileLength < 100)) {
+ engGame.log.printMessage(Log.ERROR, "savePlayer():Saving backup file for " + name + ", second try failed, aborting savePlayer");
+ blnCanSave = true;
+ return;
+ }
+ }
+ */
+ isSaveable = true;
+ }
+
+ public void close() {
+ if (name == null || name.equalsIgnoreCase("default")) {
+ return;
+ }
+ if (isClosing) {
+ /*
+ ** Already closing elsewhere
+ */
+ return;
+ }
+ isClosing = true;
+ isWorking = false;
+ isSaveNeeded = true;
+ if (!conditions.isEmpty() && game.checkConditionList.contains(this)) {
+ game.checkConditionList.remove(this);
+ }
+ removeFromGroup();
+ try {
+ game.removeDuskObject(this);
+ if (isPlayer()) {
+ try {
+ synchronized (game.scrOnLogOut) {
+ if (isSaveable) {
+ game.scrOnLogOut.varVariables.clearVariables();
+ game.scrOnLogOut.varVariables.addVariable("trigger", this);
+ game.scrOnLogOut.runScript();
+ }
+ }
+ } catch (Exception e) {
+ }
+ try {
+ outstream.writeBytes((char) 3 + "Goodbye.\n" + (char) 0);
+ } catch (Exception e) {
+ }
+ synchronized (game.playersByName) {
+ game.playersByName.remove(name.toLowerCase());
+ }
+ try {
+ savePlayer();
+ } catch (Exception e) {
+ }
+ isSaveable = false;
+ //try {
+ // rafFile.close();
+ // rafBackup.close();
+ //} catch (Exception e) {
+ //}
+ try {
+ if (following != null && following.isPet()) {
+ following.close();
+ }
+ for (LivingThing pet : game.petList) {
+ if (pet.master == this) {
+ pet.close();
+ break;
+ }
+ }
+ } catch (Exception e) {
+ }
+ try {
+ instream.close();
+ } catch (Exception e) {
+ }
+ try {
+ outstream.close();
+ } catch (Exception e) {
+ }
+ if (!(hasCondition("invis") && (privs > 2))) {
+ game.log.printMessage(Log.INFO, socket.getInetAddress().toString() + ":" + name + " has logged out");
+ game.chatMessage(name + " has logged out.", name);
+ } else {
+ game.log.printMessage(Log.INFO, socket.getInetAddress().toString() + ":" + name + " has logged out hidden from players");
+ }
+ try {
+ socket.close();
+ } catch (Exception e) {
+ }
+ isStopped = true;
+ } else if (isMob()) {
+ //try {
+ // rafFile.close();
+ // rafBackup.close();
+ //} catch (Exception e) {
+ //}
+ //game.vctMobs.remove(this);
+ } else if (isPet()) {
+ //game.vctPets.removeElement(this);
+ savePlayer();
+ //try {
+ // rafFile.close();
+ // rafBackup.close();
+ //} catch (Exception e) {
+ //}
+ }
+ } catch (Exception e) {
+ game.log.printError("close():While closing " + name, e);
+ }
+ }
+
+ public void closeNoMsgPlayer() {
+ // Disabled this check... if this is called, the player needs to be closed.
+ // if (blnIsClosing)
+ // {
+ // /*
+ // ** Already closing elsewhere
+ // */
+ // return;
+ // }
+ isClosing = true;
+ isWorking = false;
+ removeFromGroup();
+ if (conditions.size() != 0) {
+ game.checkConditionList.remove(this);
+ }
+ game.removeDuskObject(this);
+ game.playersByName.remove(name.toLowerCase());
+ try {
+ socket.shutdownInput();
+ } catch (Exception e) {
+ }
+ try {
+ socket.shutdownOutput();
+ } catch (Exception e) {
+ }
+ try {
+ instream.close();
+ } catch (Exception e) {
+ }
+ savePlayer();
+ //try {
+ // rafFile.close();
+ // rafBackup.close();
+ //} catch (Exception e) {
+ //}
+ if (following != null && following.isPet()) {
+ following.close();
+ }
+ try {
+ outstream.close();
+ } catch (Exception e) {
+ }
+ isStopped = true;
+ game.log.printMessage(Log.INFO, socket.getInetAddress().toString() + ":" + name + " has logged out");
+ game.chatMessage(name + " has logged out.", name);
+ try {
+ socket.close();
+ } catch (Exception e) {
+ }
+ name = null;
+ }
+
+ void closeNosavePlayer() {
+ if (name == null || name.equalsIgnoreCase("default")) {
+ isStopped = true;
+ try {
+ instream.close();
+ } catch (Exception e) {
+ }
+ try {
+ socket.close();
+ } catch (Exception e) {
+ }
+ try {
+ outstream.close();
+ } catch (Exception e) {
+ }
+ return;
+ }
+ if (isClosing) {
+ /*
+ ** Already closing elsewhere
+ */
+ return;
+ }
+ isClosing = true;
+ isWorking = false;
+ isSaveable = false;
+ isSaveNeeded = false;
+ if (!conditions.isEmpty() && game.checkConditionList.contains(this)) {
+ game.checkConditionList.remove(this);
+ }
+ removeFromGroup();
+ try {
+ game.removeDuskObject(this);
+ if (isPlayer()) {
+ try {
+ synchronized (game.scrOnLogOut) {
+ //engGame.scrOnLogOut.varVariables.clearVariables();
+ //engGame.scrOnLogOut.varVariables.addVariable("trigger",this);
+ //engGame.scrOnLogOut.runScript();
+ }
+ } catch (Exception e) {
+ }
+ try {
+ outstream.writeBytes((char) 3 + "Goodbye.\n" + (char) 0);
+ } catch (Exception e) {
+ }
+ //try {
+ // rafFile.close();
+ // rafBackup.close();
+ //} catch (Exception e) {
+ //}
+ game.playersByName.remove(name.toLowerCase());
+ try {
+ instream.close();
+ } catch (Exception e) {
+ }
+ try {
+ outstream.close();
+ } catch (Exception e) {
+ }
+ try {
+ socket.close();
+ } catch (Exception e) {
+ }
+ isStopped = true;
+ } else if (isMob()) {
+ //game.vctMobs.remove(this);
+ } else if (isPet()) {
+ //game.vctPets.removeElement(this);
+ //try {
+ // rafFile.close();
+ // rafBackup.close();
+ //} catch (Exception e) {
+ //}
+ }
+ } catch (Exception e) {
+ game.log.printError("closeNosavePlayer():While closing " + name, e);
+ }
+ }
+
+ public void updateFlag(long ID, int Value) {
+ send((char) 29 + "" + ID + "\n" + Value + "\n");
+ }
+
+ public void clearFlags() {
+ send((char) 30 + "");
+ }
+
+ public boolean hasPendingMoves() {
+ synchronized (moveQueue) {
+ return !moveQueue.isEmpty();
+ }
+ }
+
+ /**
+ * Clear any pending moves and queue a new move direction
+ *
+ * @param dir n/s/e/w
+ * @return true if move is possible
+ */
+ public boolean moveAfterClear(String dir) {
+ if (getMaster() != null) {
+ if (!isPet() || getMaster().getFollowing() == this) {
+ return false;
+ }
+ }
+ synchronized (moveQueue) {
+ moveQueue.clear();
+ moveQueue.add(dir);
+ }
+ return true;
+ }
+
+ public void clearMoveQueue() {
+ synchronized (moveQueue) {
+ moveQueue.clear();
+ }
+ }
+
+ /**
+ * Process one queued move
+ */
+ public void moveTick() {
+ synchronized (moveQueue) {
+ if (moveQueue.isEmpty())
+ return;
+
+ String dir = moveQueue.removeFirst();
+
+ if (dir != null) {
+ switch (dir.charAt(0)) {
+ case 'n':
+ moveN();
+ break;
+ case 's':
+ moveS();
+ break;
+ case 'w':
+ moveW();
+ break;
+ case 'e':
+ moveE();
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Send this to a specific destination.
+ *
+ * This is a completely new implementation using the map
+ *
+ * @param destX
+ * @param destY
+ * @param goon If true, go to exact location, otherwise only next to it
+ * @return
+ */
+ public String goTo(int destX, int destY, boolean goon) {
+ if (master != null) {
+ if (!isPet() || master.following == this) {
+ return "You can't move while you're following someone.";
+ }
+ }
+ if (goon && !game.canMoveTo(destX, destY, this)) {
+ return "You can't move onto that location.";
+ }
+ if (Math.abs(destX - x) > game.viewrange || Math.abs(destY - y) > game.viewrange) {
+ return null;
+ }
+ synchronized (moveQueue) {
+ moveQueue.clear();
+
+ TileMap.MoveListener ml = new TileMap.MoveListener() {
+ @Override
+ public boolean canMoveto(MapData md) {
+ return game.canMoveTo(md.x, md.y, LivingThing.this);
+ }
+ };
+ int mflags = goon ? 0 : TileMap.SKIP_END;
+
+ for (MoveData md : game.map.move(x, y, destX, destY, mflags, ml)) {
+ moveQueue.add(md.direction);
+ }
+ }
+ return null;
+ }
+
+ // FIXME: should probably be in DuskEngine
+ protected synchronized void moveTo(int newLocX, int newLocY, MessageType dir, int intNewStep) {
+ if (privs < 5 && (newLocX >= (game.map.getCols() - 1)
+ || newLocY >= (game.map.getRows() - 1)
+ || newLocX < 0
+ || newLocY < 0)) {
+ return;
+ }
+ // Movement during combat is disallowed here
+ // need to check min range in the battle and see if anything is at 1 with this livingthing
+// if (privs>1 || (batBattle == null && !blnSleep && engGame.canMoveTo(newLocX,newLocY,this)))
+ if (privs > 1 || (isMoveable && !isSleeping && game.canMoveTo(newLocX, newLocY, this))) {
+ if (isMob()) {
+ int maxY = originalY + game.viewrange;
+ int minY = originalY - game.viewrange;
+ int maxX = originalX + game.viewrange;
+ int minX = originalX - game.viewrange;
+ if ((newLocY > maxY) || (newLocY < minY) || (newLocX > maxX) || (newLocX < minX)) {
+ return;
+ }
+ }
+ } else {
+ return;
+ }
+ int oldLocX = x;
+ int oldLocY = y;
+ // Move it from cell to cell
+ game.moveDuskObject(this, newLocX, newLocY, dir);
+ try {
+ imagestep = intNewStep;
+ if (isPlayer()) {
+ if (game.overMerchant(oldLocX, oldLocY) != null) {
+ offMerchant();
+ }
+ if (game.overPlayerMerchant(oldLocX, oldLocY) != null) {
+ offMerchant();
+ }
+ updateMap();
+ }
+ Script scrStore;
+ try {
+ scrStore = (Script) game.tileAction.get((int) game.map.getTile(x, y));
+ synchronized (scrStore) {
+ scrStore.varVariables.clearVariables();
+ scrStore.varVariables.addVariable("trigger", this);
+ scrStore.runScript();
+ }
+ } catch (Exception e) {
+ }
+ Script.exec("defMoveActions/" + x + "_" + y, game, this);
+
+ //move follower
+ if (following != null) {
+ //don't move follower if leader has moved onto follower's tile
+ if ((following.x == newLocX) && (following.y == newLocY)) {
+ return;
+ }
+ if (Math.abs(following.x - oldLocX) + Math.abs(following.y - oldLocY) > 1) {
+ if (following.isPet()) {
+ if (following.following != null) {
+ chatMessage(following.following.name + " is no longer following you.");
+ following.following.chatMessage("You are no longer following " + name + ".");
+ following.following.master = null;
+ following.following = null;
+ }
+ following.changeLocBypass(oldLocX, oldLocY);
+ } else {
+ chatMessage(following.name + " is no longer following you.");
+ following.chatMessage("You are no longer following " + name + ".");
+ following.master = null;
+ following = null;
+ }
+ } else if (following.y > oldLocY) {
+ following.moveN();
+ } else if (following.y < oldLocY) {
+ following.moveS();
+ } else if (following.x > oldLocX) {
+ following.moveW();
+ } else if (following.x < oldLocX) {
+ following.moveE();
+ }
+ }
+ if (isPlayer()) {
+ game.refreshEntities(this);
+ }
+ //game.removeIfCanNoLongerSee(this);
+ } catch (Exception e) {
+ game.log.printError("moveTo()", e);
+ }
+ }
+
+ public void moveN() {
+ moveTo(x, y - 1, MessageType.MoveNorth, 0);
+ }
+
+ public void moveS() {
+ moveTo(x, y + 1, MessageType.MoveSouth, 2);
+ }
+
+ public void moveW() {
+ moveTo(x - 1, y, MessageType.MoveWest, 4);
+ }
+
+ public void moveE() {
+ moveTo(x + 1, y, MessageType.MoveEast, 6);
+ }
+
+ public DuskObject removeEntity(long id) {
+ synchronized (nearEntities) {
+ DuskObject o = nearEntities.remove(id);
+
+ if (o != null) {
+ System.out.println("Removing client entity " + id + " from " + name);
+ send(MessageType.RemoveEntity, id + "\n");
+ }
+ return o;
+ }
+ }
+
+ public boolean nearEntity(long id) {
+ synchronized (nearEntities) {
+ return nearEntities.containsKey(id);
+ }
+ }
+
+ public void addEntity(DuskObject ent) {
+ synchronized (nearEntities) {
+ if (nearEntities.containsKey(ent.ID))
+ return;
+
+ System.out.println("Adding client entity " + ent.ID + " " + ent.name + " to " + name);
+
+ nearEntities.put(ent.ID, ent);
+ }
+
+ // Only sent to player if they can see it?
+ if (!ent.isLivingThing()
+ || game.canSeeLivingThing(this, (LivingThing) ent)) {
+ System.out.println("Adding entity " + ent.name + " to " + name);
+ //send(MessageType.AddEntity, ent.toEntity());
+ send(ent.toMessage(MessageType.AddEntity));
+ } else {
+ System.out.println("Not adding entity " + ent.name + " to " + name);
+ }
+ }
+
+ /**
+ * Set a new set of near-entities
+ *
+ * @param ent
+ */
+ public void setEntities(List<DuskObject> newEntities) {
+ HashMap<Long, DuskObject> left = (HashMap<Long, DuskObject>) nearEntities.clone();
+
+ if (false) {
+ System.out.println("setting entities on " + name);
+ for (DuskObject d : left.values()) {
+ System.out.println(" - " + d.ID + " " + d.name);
+ }
+ for (DuskObject d : newEntities) {
+ System.out.println(" + " + d.ID + " " + d.name);
+ }
+ }
+
+ for (DuskObject o : newEntities) {
+ if (left.containsKey(o.ID)) {
+ // Have this already, do nothing
+ left.remove(o.ID);
+ } else {
+ // This is a new one
+ //nearEntities.put(o.ID, o);
+ game.addEntity(o);
+ }
+ }
+ // anything left over must be removed
+ for (long id : left.keySet()) {
+ removeEntity(id);
+ }
+ }
+
+ public void changeLoc(int newLocX, int newLocY) {
+ if (privs > 1 || (battle == null && !isSleeping && game.canMoveTo(newLocX, newLocY, this))) {
+ if (isMob()) {
+ if (!(Math.abs(originalX - newLocX) < game.viewrange && Math.abs(originalY - newLocY) < game.viewrange)) {
+ return;
+ }
+ }
+ changeLocBypass(newLocX, newLocY);
+ }
+ }
+
+ synchronized public void changeLocBypass(int newLocX, int newLocY) {
+ int oldLocX = x;
+ int oldLocY = y;
+ game.removeDuskObject(this);
+ x = newLocX;
+ y = newLocY;
+ try {
+ if (isPlayer()) {
+ updateMap();
+ if (game.overMerchant(oldLocX, oldLocY) != null) {
+ offMerchant();
+ }
+ if (game.overPlayerMerchant(oldLocX, oldLocY) != null) {
+ offMerchant();
+ }
+ }
+ //update entity:
+ if (isWorking) {
+ game.addDuskObject(this);
+ }
+ Script scrStore;
+ try {
+ scrStore = (Script) game.tileAction.get((int) game.map.getTile(newLocX, newLocY));
+ synchronized (scrStore) {
+ scrStore.varVariables.clearVariables();
+ scrStore.varVariables.addVariable("trigger", this);
+ scrStore.runScript();
+ }
+ } catch (Exception e) {
+ }
+ Script.exec("defMoveActions/" + newLocX + "_" + newLocY, game, this);
+ if (following != null) {
+ following.changeLocBypass(oldLocX, oldLocY);
+ }
+ if (isPlayer()) {
+ game.refreshEntities(this);
+ }
+ } catch (Exception e) {
+ game.log.printError("changeLocBypass():" + name + " disconnected", e);
+ isStopped = true;
+ }
+ }
+
+ public void updateMap() {
+ /*
+ StringBuilder sb = new StringBuilder();
+ //update map:
+
+ sb.append(x).append("\n");
+ sb.append(y).append("\n");
+
+ int r = game.viewrange;
+ for (int mx = x - r; mx <= x + r; mx++) {
+ for (int my = y - r; my <= y + r; my++) {
+ if (game.map.inside(mx, my))
+ sb.append(game.map.getTile(mx, my)).append("\n");
+ else
+ sb.append("0\n");
+ }
+ }
+
+ send(MessageType.UpdateLocMap, sb.toString());*/
+
+ int r = game.viewrange;
+
+ short[] tiles = new short[(r * 2 + 1) * (r * 2 + 1)];
+ int i = 0;
+ //System.out.printf("map at %d,%d\n", x, y);
+ for (int my = y - r; my <= y + r; my++) {
+ for (int mx = x - r; mx <= x + r; mx++) {
+ tiles[i++] = game.map.inside(mx, my) ? game.map.getTile(mx, my) : 0;
+ //System.out.printf("%s%3d", game.map.inside(mx, my) ? " " : "*", tiles[i-1]);
+ }
+ //System.out.println("\n");
+ }
+
+ send(ServerMessage.mapMessage(x, y, tiles));
+ }
+
+ public void chatMessage(String inMessage) {
+ if (inMessage == null) {
+ return;
+ }
+ if (isPlayer()) {
+ send(MessageType.Chat, inMessage + "\n");
+ }
+ if (charmer != null) {
+ charmer.chatMessage("From " + name + ": " + inMessage);
+ return;
+ }
+ }
+
+ public void chatMessage(int red, int green, int blue, String inMessage) {
+ if (inMessage == null) {
+ return;
+ }
+ if (isPlayer()) {
+ if (!coloron) {
+ chatMessage(inMessage);
+ return;
+ }
+ String strResult = "" + (char) 23;
+ strResult += red + "\n" + green + "\n" + blue + "\n" + inMessage + "\n";
+ send(strResult);
+ }
+ if (charmer != null) {
+ charmer.chatMessage(red, green, blue, "From " + name + ": " + inMessage);
+ return;
+ }
+ }
+
+ public int getCharacterPoints() {
+ int result = wisd
+ + inte
+ + stre
+ + dext
+ + cons
+ + ((maxhp) / 10)
+ + ((maxmp) / 10)
+ + totalSkillValue();
+ return result;
+ }
+
+ public int getTotalPoints() {
+ int result = getCharacterPoints()
+ + getArmorMod()
+ + (getDamMod() - 100);
+ return result;
+ }
+
+ public Item getItem(String strStore) {
+ // Check worn items by location, TBH not really sure of the point of this
+ int where = Equipment.toIndex(strStore);
+ if (where != -1) {
+ Item item = wornItems.getWorn(where);
+ if (item != null)
+ return item;
+ }
+
+ int i,
+ intNumber = 1;
+ i = strStore.indexOf('.');
+ if (i != -1) {
+ try {
+ intNumber = Integer.parseInt(strStore.substring(0, i));
+ strStore = strStore.substring(i + 1, strStore.length());
+ } catch (NumberFormatException e) {
+ intNumber = 1;
+ }
+ }
+ Item itmStore;
+ LinkedList<Item> qStore;
+ qStore = itemList.get(strStore);
+ if (qStore != null) {
+ if (qStore.size() >= intNumber) {
+ itmStore = (Item) qStore.element();
+ return itmStore;
+ }
+ }
+ return null;
+ }
+
+ public Item getItemAndRemove(String strStore) {
+ int i,
+ intNumber = 1;
+ i = strStore.indexOf(".");
+ if (i != -1) {
+ try {
+ intNumber = Integer.parseInt(strStore.substring(0, i));
+ strStore = strStore.substring(i + 1, strStore.length());
+ } catch (NumberFormatException e) {
+ intNumber = 1;
+ }
+ }
+ if (intNumber == 0) {
+ return null;
+ }
+ Item itmStore;
+ Item itmFound = null;
+ LinkedList<Item> qStore;
+ qStore = itemList.get(strStore);
+ if (qStore != null) {
+ if (!qStore.isEmpty()) {
+ itmStore = (Item) qStore.element();
+ itmFound = itmStore;
+ while (intNumber != 0 && itmStore != null) {
+ qStore.pop();
+ intNumber--;
+ }
+ if (qStore.size() < 1) {
+ itemList.removeElement(strStore);
+ }
+ } else {
+ itemList.removeElement(strStore);
+ }
+ }
+ return itmFound;
+ }
+
+ public int getArmorMod() {
+ return wornItems.armourMod();
+ }
+
+ public int getArmorModWithBonus() {
+ return getArmorMod() + ((dext + dextbon) / 10) + acbon;
+ }
+
+ public int getDamMod() {
+ Item item = wornItems.getWorn(Equipment.WIELD);
+ if (item != null)
+ return item.intMod;
+ return 100;
+ }
+
+ public int getDamModWithBonus() {
+ return getDamMod() + dammodbon;
+ }
+
+ public int getRange() {
+ Item item = wornItems.getWorn(Equipment.WIELD);
+
+ if (item == null) {
+ return 1;
+ }
+ return item.range();
+ }
+
+ public int getRangeWithBonus() {
+ return getRange() + rangebon;
+ }
+
+ public void weaponDam(int damage) {
+ if (isMob()) //Mobs weapons are invincible
+ {
+ return;
+ }
+
+ Item item = wornItems.damageItem(Equipment.WIELD, damage);
+ if (item != null) {
+ chatMessage("Your " + item.name + " breaks.");
+ onUnwear(item);
+ if (isPlayer()) {
+ updateEquipment();
+ updateStats();
+ }
+ }
+ }
+
+ public void armorDam(int damage) {
+ if (isMob()) //Mobs armor is invincible
+ {
+ return;
+ }
+ int armour = wornItems.armourCount();
+ if (armour == 0) {
+ return;
+ }
+
+ for (int i = Equipment.ARMS; i < Equipment.WEARING_COUNT; i++) {
+ Item item = wornItems.damageItem(Equipment.WIELD, damage);
+ if (item != null) {
+ chatMessage("Your " + item.name + " breaks.");
+ onUnwear(item);
+ updateStats();
+ updateEquipment();
+ }
+ }
+ }
+
+ public void useItem(String strStore, int mustBeType) {
+ String strStore2 = null;
+ int i2 = 0;
+ if (strStore.startsWith("\"")) {
+ char c, c2;
+
+ strStore2 = "";
+ i2 = 1;
+ try {
+ while (true) {
+ c = strStore.charAt(i2);
+ if (c == '\\') {
+ c2 = strStore.charAt(i2 + 1);
+ strStore2 += c2;
+ } else if (c == '\"') {
+ i2++;
+ break;
+ } else {
+ strStore2 += c;
+ }
+ i2++;
+ }
+ } catch (Exception e) {
+ chatMessage("You don't have that.");
+ return;
+ }
+ } else {
+ i2 = strStore.indexOf(" ");
+ if (i2 == -1) {
+ strStore2 = strStore;
+ i2 = strStore.length();
+ } else {
+ strStore2 = strStore.substring(0, i2);
+ }
+ }
+ if (strStore.length() > i2 + 1) {
+ strStore = strStore.substring(i2 + 1);
+ }
+ Item itmStore = getItem(strStore2);
+ if (itmStore == null) {
+ chatMessage("You don't have that.");
+ return;
+ }
+ if (itmStore.strOnUseScript == null) {
+ chatMessage("That has no use.");
+ return;
+ }
+ if (mustBeType != -1 && itmStore.intType != mustBeType) {
+ chatMessage("You can't use that like that.");
+ return;
+ }
+ if (itmStore.intUses == 0) {
+ chatMessage("That item is used up.");
+ return;
+ }
+ try {
+ Script scrStore = new Script("scripts/" + itmStore.strOnUseScript, game, false);
+// synchronized(scrStore)
+// {
+ scrStore.varVariables.addVariable("trigger", this);
+ scrStore.varVariables.addVariable("itemname", itmStore.name);
+ scrStore.varVariables.addVariable("mod", itmStore.intMod);
+ scrStore.runScript();
+ scrStore.close();
+// }
+ } catch (Exception e) {
+ chatMessage("That has no use.");
+ return;
+ }
+ itmStore.intUses--;
+ }
+
+ public void castSpell(String spell) {
+ String strStore = "",
+ strStore2 = "";
+ int intStore,
+ intStore2;
+ LivingThing target = null;
+ // FIXME: de-quote and/or command parser
+ int i2 = 0;
+ if (spell.startsWith("\"")) {
+ char c, c2;
+ i2 = 1;
+ try {
+ while (true) {
+ c = spell.charAt(i2);
+ i2++;
+ if (c == '\"') {
+ break;
+ }
+ if (c == '\\') {
+ c2 = spell.charAt(i2);
+ strStore2 += c2;
+ } else {
+ strStore2 += c;
+ }
+ }
+ } catch (Exception e) {
+ chatMessage("You don't know that spell.");
+ }
+ } else {
+ i2 = spell.indexOf(" ");
+ if (i2 == -1) {
+ strStore2 = spell;
+ i2 = spell.length();
+ } else {
+ strStore2 = spell.substring(0, i2);
+ }
+ }
+ if (spell.length() > i2 + 1) {
+ spell = spell.substring(i2 + 1);
+ } else {
+ spell = null;
+ }
+ try {
+ try (RandomAccessFile rafSpell = new RandomAccessFile("defSpells/" + strStore2.toLowerCase(), "r")) {
+ strStore = rafSpell.readLine();
+ } catch (FileNotFoundException x) {
+ chatMessage("You don't know that spell.");
+ return;
+ }
+ SpellGroup grpStore = game.getSpellGroup(strStore);
+ intStore = getSpell(strStore);
+ intStore2 = grpStore.getSpellNumber(strStore2);
+ if (grpStore == null) {
+ chatMessage("You don't know that spell.");
+ return;
+ }
+ // FIXME: reorder this so the script is only created after the checks
+ Script scrSpell;
+ try {
+ scrSpell = new Script("defSpellGroups/" + intStore2 + " " + strStore.toLowerCase(), game, false);
+ } catch (Exception e) {
+ chatMessage("You don't know that spell.");
+ return;
+ }
+ if (intStore2 != 0) //change number to percent
+ {
+ intStore2 = (100 * intStore2) / (grpStore.vctSpells.size() - 1);
+ }
+ if (intStore == 0 || intStore < intStore2) {
+ chatMessage("You don't know that spell.");
+ scrSpell.close();
+ return;
+ }
+ intStore2 = (110 - (intStore - intStore2)) / 2; //change percent to mp cost
+ if (intStore2 > mp) {
+ chatMessage("You don't have enough mp to cast that spell.");
+ scrSpell.close();
+ return;
+ }
+ mp -= intStore2;
+ scrSpell.varVariables.addVariable("caster", this);
+ if (spell == null) {
+ scrSpell.runScript();
+ } else {
+ scrSpell.runScript(spell);
+ }
+ scrSpell.close();
+ if (isPlayer()) {
+ updateInfo();
+ }
+ } catch (Exception e) {
+ game.log.printError("castSpell()", e);
+ }
+ }
+
+ public boolean isWearing(String name) {
+ return wornItems.isWearing(name);
+ }
+
+ private void unwear(Item old) {
+ if (old != null) {
+ itemList.addElement(old);
+ onUnwear(old);
+ }
+ }
+
+ private void unwear(int index) {
+ unwear(wornItems.unwear(index));
+ }
+
+ public void unWear(String strStore) {
+ int index = Equipment.toIndex(strStore);
+
+ if (index != -1) {
+ unwear(index);
+ } else if (strStore.equalsIgnoreCase("all")) {
+ for (int i = 0; i < Equipment.WEARING_COUNT; i++) {
+ unwear(i);
+ }
+ } else {
+ unwear(wornItems.unwearByName(strStore));
+ }
+ if (isPlayer()) {
+ updateStats();
+ updateEquipment();
+ updateItems();
+ }
+ }
+
+ public void onWear(Item trigger) {
+ if (trigger.strOnWearScript != null) {
+ try {
+ Script scrStore = new Script("scripts/" + trigger.strOnWearScript, game, false);
+ scrStore.varVariables.addVariable("trigger", this);
+ scrStore.varVariables.addVariable("itemname", trigger.name);
+ scrStore.varVariables.addVariable("mod", trigger.intMod);
+ scrStore.runScript();
+ scrStore.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ public void onUnwear(Item trigger) {
+ if (trigger.strOnUnWearScript != null) {
+ try {
+ Script scrStore = new Script("scripts/" + trigger.strOnUnWearScript, game, false);
+ scrStore.varVariables.addVariable("trigger", this);
+ scrStore.varVariables.addVariable("itemname", trigger.name);
+ scrStore.varVariables.addVariable("mod", trigger.intMod);
+ scrStore.runScript();
+ scrStore.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ public boolean hasCondition(String strStore) {
+ for (Condition cndStore : conditions) {
+ if (cndStore.name.equalsIgnoreCase(strStore)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void addCondition(Condition cndStore) {
+ if (conditions.isEmpty()) {
+ game.checkConditionList.add(this);
+ } else {
+ for (int i = 0; i < conditions.size(); i++) {
+ Condition cndStore2 = conditions.get(i);
+ if (cndStore2.name.equalsIgnoreCase(cndStore.name)) {
+ conditions.remove(i);
+ i--;
+ cndStore2.onEnd(game, this);
+ }
+ }
+ }
+ conditions.add(cndStore);
+ cndStore.onStart(game, this);
+ updateStats();
+ }
+
+ public void removeCondition(String strName) {
+ Condition cndStore;
+ for (int i = 0; i < conditions.size(); i++) {
+ cndStore = (Condition) conditions.get(i);
+ if (strName.equalsIgnoreCase(cndStore.name)) {
+ conditions.remove(i);
+ if (conditions.isEmpty()) {
+ game.checkConditionList.remove(this);
+ }
+ cndStore.onEnd(game, this);
+ updateStats();
+ return;
+ }
+ }
+ updateStats();
+ }
+
+ public DuskObject getLocalObject(String name) {
+ return game.findVisibleObject(this, name);
+ }
+
+ public void removeFromGroup() {
+ if (following != null && following.isPet()) {
+ if (master != null) {
+ try {
+ chatMessage("You are no longer following " + master.name + ".");
+ } catch (Exception e) {
+ }
+ try {
+ master.chatMessage(name + " is no longer following you.");
+ } catch (Exception e) {
+ }
+ master.following = following.following;
+ }
+ if (following.following != null) {
+ following.following.master = master;
+ }
+ if (!isPet()) {
+ master = null;
+ }
+ following.following = null;
+ } else {
+ if (master != null) {
+ try {
+ chatMessage("You are no longer following " + master.name + ".");
+ } catch (Exception e) {
+ }
+ try {
+ master.chatMessage(name + " is no longer following you.");
+ } catch (Exception e) {
+ }
+ master.following = following;
+ }
+ if (following != null) {
+ following.master = master;
+ }
+ if (!isPet()) {
+ master = null;
+ }
+ following = null;
+ }
+ }
+
+ public void run() {
+ connectionThread = Thread.currentThread();
+ try {
+ do {
+ name = instream.readLine();
+ if (name != null) {
+ name = name.trim();
+ }
+ } while (!getPlayer());
+ if (!isWorking) {
+ return;
+ }
+ } catch (Exception e) {
+ game.log.printError("LivingThing.run():start", e);
+ closeNosavePlayer();
+ return;
+ }
+ connectionThread.setName("LivingThing(" + name + ")");
+ sendThread.setName("LivingThing(" + name + ").send");
+ resizeMap();
+ changeLocBypass(x, y);
+ updateInfo();
+ updateStats();
+ updateItems();
+ updateEquipment();
+ updateActions();
+ if (game.blnMusic) {
+ updateMusic();
+ playMusic(0);
+ }
+ if (!(hasCondition("invis") && (privs > 2))) {
+ game.log.printMessage(Log.INFO, socket.getInetAddress().toString() + ":" + name + " has entered the world");
+ game.chatMessage(name + " has entered the world.", name);
+ } else {
+ chatMessage("You have entered the world hidden from players.");
+ game.log.printMessage(Log.INFO, socket.getInetAddress().toString() + ":" + name + " has entered the world hidden from players");
+ }
+ String strInput,
+ strStore;
+ isSaveable = true;
+ isReady = true;
+ while (true) {
+ if (isStopped) {
+ return;
+ }
+ try {
+ if (!isHalted) {
+ strInput = instream.readLine();
+ if (strInput != null) {
+ strInput = strInput.trim();
+ }
+ strStore = Commands.parseCommand(this, game, strInput);
+ if (strStore != null) {
+ chatMessage(strStore);
+ }
+ }
+ } catch (Exception e) {
+ game.log.printError("LivingThing.run():" + name + " disconnected", e);
+ close();
+ return;
+ }
+ }
+ }
+
+ boolean getPlayer() {
+ if (!game.isGoodName(name)) {
+ chatMessage("Not a valid name. This may because you left it blank, used invalid symbols, or made it too long. Please try again.");
+ return false;
+ }
+ String strStore;
+ int i;
+ LivingThing thnStore;
+ try {
+ File filStore = new File("users/" + name.toLowerCase());
+ if (!filStore.exists() || filStore.length() < 100) {
+ File filBackup = new File("users/" + name.toLowerCase() + ".backup");
+ if (filBackup.exists()) {
+ filBackup.renameTo(filStore);
+ }
+ }
+
+ String strIP = socket.getInetAddress().toString();
+ int ip = strIP.indexOf("/");
+ strIP = strIP.substring(ip + 1, strIP.length());
+
+ if (filStore.exists()) {
+ try (RandomAccessFile rafFile = new RandomAccessFile("users/" + name.toLowerCase(), "r")) {
+ chatMessage("enter your password:");
+ password = instream.readLine();
+ if (!password.equals(rafFile.readLine())) {
+ rafFile.close();
+ game.log.printMessage(Log.INFO, socket.getInetAddress().toString() + ":" + name + " entered the wrong password");
+ Variable failCount = game.varIP.getVariable(strIP);
+ if (failCount != null) {
+ int fc = failCount.intValue();
+ if (fc >= 4) {
+ game.banAddress(strIP);
+ chatMessage("Too many login failures, try again in an hour.");
+ send("Goodbye.\n" + (char) 0);
+ Thread.sleep(1000);
+ closeNosavePlayer();
+ rafFile.close();
+ return true;
+ } else {
+ game.varIP.addVariable(strIP, fc + 1);
+ }
+ } else {
+ game.varIP.addVariable(strIP, (double) 1);
+ }
+ Thread.sleep(3000);
+ chatMessage("Incorrect Password.");
+ chatMessage("Enter your login name: ");
+ return false;
+ }
+ } catch (Exception e) {
+ game.log.printError("getPlayer():" + socket.getInetAddress().toString() + ":" + name, e);
+ closeNosavePlayer();
+ return true;
+ }
+ } else {
+ File fileStore = new File("pets/" + name.toLowerCase());
+ if (fileStore.exists()) {
+ chatMessage(name + " is already in use. Please choose another.");
+ return false;
+ }
+ chatMessage(name + ", Is that correct? (yes/no)");
+ if (!instream.readLine().equalsIgnoreCase("yes")) {
+ chatMessage("Then what IS your name?");
+ return false;
+ }
+ chatMessage("Enter a new password:");
+ password = instream.readLine();
+ chatMessage("Confirm that password:");
+ while (!password.equals(instream.readLine())) {
+ chatMessage("Passwords did not match, enter a new password:");
+ password = instream.readLine();
+ chatMessage("Confirm that password:");
+ }
+ }
+ game.varIP.removeVariable(strIP);
+ try {
+ wornItems = new Equipment();
+ itemList = new ItemList();
+ conditions.clear();
+ nearEntities.clear();
+ flags.clear();
+ ignoreList.clear();
+ chatMessage("Login Accepted.");
+ proceed();
+ chatMessage("This game is running DuskServer v" + game.version + ". http://dusk.wesowin.org/");
+ chatMessage("Started at " + game.datStart.toString() + ".");
+ for (LivingThing lt : game.playersByName.values()) {
+ if (name.equalsIgnoreCase(lt.name)) {
+ game.log.printMessage(Log.INFO, socket.getInetAddress().toString() + ":" + name + " tried to log in twice");
+ chatMessage("That user is already logged in. They are being logged out.");
+ lt.chatMessage("There has been another logon under this name, you are being logged out.");
+ lt.close();
+ break;
+ }
+ // Second IP Filter check to catch delayed sign-ons
+ if (game.blnIPF) {
+ String IP = lt.socket.getInetAddress().toString();
+ if (IP.equalsIgnoreCase(socket.getInetAddress().toString())) {
+ chatMessage("There's already a player connected from your IP address.");
+ Thread.sleep(1000);
+ closeNosavePlayer();
+ return false;
+ }
+ }
+ }
+ game.playersByName.put(this.name.toLowerCase(), this);
+ game.onStart(this);
+ try (RandomAccessFile rafFile = new RandomAccessFile("users/default", "r")) {
+ strStore = rafFile.readLine();
+ while (!(strStore == null || strStore.equals("."))) {
+ parseUserFile(rafFile, strStore);
+ strStore = rafFile.readLine();
+ }
+ }
+ } catch (Exception e) {
+ game.log.printError("getPlayer():While loading default user file for " + name, e);
+ }
+ strStore = name.toLowerCase();
+ File filPlayer = new File("users/" + strStore);
+ File filBackup = new File("users/" + strStore + ".backup");
+ File filCheck;
+ int i2 = 0;
+ if (filBackup.exists()) {
+ if (filPlayer.length() > filBackup.length()) {
+ filCheck = new File("backup/" + strStore + ".possiblyDamaged");
+ while (filCheck.exists()) {
+ i2++;
+ filCheck = new File("backup/" + strStore + ".possiblyDamaged." + i2);
+ }
+ filBackup.renameTo(filCheck);
+ } else if (filPlayer.length() < filBackup.length()) {
+ filCheck = new File("backup/" + strStore + ".possiblyDamaged");
+ while (filCheck.exists()) {
+ i2++;
+ filCheck = new File("backup/" + strStore + ".possiblyDamaged." + i2);
+ }
+ filPlayer.renameTo(filCheck);
+ filBackup.renameTo(new File("users/" + strStore));
+ }
+ }
+ /*
+ ** Load the user
+ */
+ file = new File("users/", strStore);
+ backup = new File("users/", strStore + ".backup");
+ try (RandomAccessFile rafFile = new RandomAccessFile(file, "rw")) {
+ strStore = rafFile.readLine();
+ while (!(strStore == null || strStore.equals("."))) {
+ parseUserFile(rafFile, strStore);
+ strStore = rafFile.readLine();
+ }
+ }
+ /*
+ ** Try to load a pet, if they don't already have one
+ */
+ if (following == null) {
+ following = new LivingThing("default", null, this, game);
+ if (following.name.equalsIgnoreCase("default")) {
+ following.closeNosavePlayer();
+ following = null;
+ }
+ }
+ } catch (Exception e) {
+ game.log.printError("getPlayer():While loading file for " + name, e);
+ closeNosavePlayer();
+ return true;
+ }
+ loadRace();
+ isLoaded = true;
+ if (following != null) {
+ following.isLoaded = true;
+ following.changeLocBypass(x, y);
+ }
+ return true;
+ }
+
+ String askRace(String strRaceDir, String prompt) throws IOException {
+ File filRaces = new File(strRaceDir);
+ String strList[] = filRaces.list();
+ StringBuilder sb = new StringBuilder(prompt);
+ sb.append("\n");
+ for (String s : strList) {
+ sb.append(s).append("\n");
+ }
+ sb.append(".\n");
+ String s = sb.toString();
+
+ // ??
+ if (isPlayer()) {
+ send(MessageType.ChooseRace, s);
+ }
+ if (charmer != null) {
+ charmer.send(MessageType.ChooseRace, s);
+ }
+ if (isPet()) {
+ return master.instream.readLine().toLowerCase();
+ } else {
+ return instream.readLine().toLowerCase();
+ }
+ }
+
+ public void loadRace() {
+ String s;
+ String dir;
+ if (isPet()) {
+ dir = "defPets";
+ } else {
+ dir = "defRaces";
+ }
+ try {
+ if (race == null || !(new File(dir + "/" + race).exists())) {
+ s = askRace(dir, "Choose one of the following races:");
+ // FIXME: check this isn't broken
+ File filCheck = new File(dir + "/" + s);
+ while (s.equals("") || !filCheck.exists()) {
+ s = askRace(dir, "That is not a valid race, please choose again.");
+ filCheck = new File(dir + "/" + s);
+ }
+ race = s;
+ }
+ loadRaceFile(new File(dir + "/" + race), true);
+ } catch (Exception e) {
+ game.log.printError("loadRace():Loading " + name + "'s race file \"" + dir + "/" + race + "\"", e);
+ }
+ }
+
+ public void unloadRace() {
+ String dir;
+ if (isPet()) {
+ dir = "defPets";
+ } else {
+ dir = "defRaces";
+ }
+ try {
+ if (race == null || !(new File(dir + "/" + race).exists())) {
+ race = null;
+ return;
+ }
+ loadRaceFile(new File(dir + "/" + race), false);
+ } catch (Exception e) {
+ game.log.printError("unloadRace():Un-loading " + name + "'s race file \"" + dir + "/" + race + "\"", e);
+ }
+ race = null;
+ }
+
+ public void updateAppletImages() {
+ String strResult = "" + (char) 1;
+ strResult += game.strRCAddress + "\n";
+ try {
+ send(strResult);
+ } catch (Exception e) {
+ game.log.printError("updateAppletImages()", e);
+ }
+ }
+
+ public void updateApplicationImages() {
+ String strResult = "" + (char) 1;
+ strResult += game.strRCName + "\n";
+ try {
+ send(strResult);
+ } catch (Exception e) {
+ game.log.printError("updateApplicationImages()", e);
+ }
+ }
+
+ public void updateMusic() {
+ /*try
+ {
+ String strResult="";
+ String strStore,
+ strStore2;
+ int count=0;
+ RandomAccessFile rafMusic;
+
+ rafMusic = new RandomAccessFile("music0","r");
+ strStore = "";
+ try
+ {
+ strStore2 = rafMusic.readLine();
+ while (!(strStore2 == null || strStore2.equals("")))
+ {
+ strStore += strStore2+"\n";
+ strStore2 = rafMusic.readLine();
+ count++;
+ }
+ }catch (Exception e)
+ {
+ }
+ strResult += ""+count+"\n"+strStore;
+ rafMusic.close();
+ rafMusic = new RandomAccessFile("music1","r");
+ strStore = "";
+ count=0;
+ try
+ {
+ strStore2 = rafMusic.readLine();
+ while (!(strStore2 == null || strStore2.equals("")))
+ {
+ strStore += strStore2+"\n";
+ strStore2 = rafMusic.readLine();
+ count++;
+ }
+ }catch (Exception e)
+ {
+ }
+ rafMusic.close();
+ strResult += ""+count+"\n"+strStore;
+ send((char)11+""+2+"\n"+strResult);
+ }catch(Exception e)
+ {
+ engGame.log.printError("updateMusic()", e);
+ }*/
+ }
+
+ public void playMusic(int type) {
+ /*try
+ {
+ send(""+((char)12)+""+type+"\n");
+ }catch(Exception e)
+ {
+ engGame.log.printError("playMusic()", e);
+ }*/
+ }
+
+ public void playSFX(int intSFX) {
+ if (audioon) {
+ try {
+ send((char) 15 + "" + intSFX + "\n");
+ } catch (Exception e) {
+ game.log.printError("playSFX()", e);
+ }
+ }
+ }
+
+ public void updateActions() {
+ try {
+ if (isPlayer()) {
+ String strResult = "" + (char) 10;
+ if (battle != null) {
+ strResult += "flee\n";
+ } else {
+ if (isSleeping) {
+ strResult += "wake\n";
+ } else {
+ strResult += "sleep\n";
+ }
+ }
+ strResult += ".\n";
+ send(strResult);
+ }
+ } catch (Exception e) {
+ game.log.printError("updateActions()", e);
+ }
+ }
+
+ // FIXME: I think this should be encapsulated in a more desriptive message
+ public void updateEquipment() {
+ try {
+ send(MessageType.UpdateEquipment, wornItems.toEntity());
+ } catch (Exception e) {
+ game.log.printError("updateEquipment():" + name + " disconnected", e);
+ isStopped = true;
+ return;
+ }
+ }
+
+ public void send(MessageType type, String data) {
+ if (isPlayer() && isWorking && !isClosing) {
+ // FIXME: put code in senddata
+ messageQueue.offer(ServerMessage.stringMessage(type, data));
+ }
+ }
+
+ public void send(ServerMessage msg) {
+ if (isPlayer() && isWorking && !isClosing) {
+ messageQueue.offer(msg);
+ }
+ }
+
+ public void send(String data) {
+ if (isPlayer() && isWorking && !isClosing) {
+ messageQueue.offer(ServerMessage.stringMessage(data));
+ }
+ }
+
+ /* public void send(byte data)
+ {
+ if (isPlayer() && blnWorking && !blnIsClosing)
+ {
+ SendData sd = new SendData(data);
+ qMessage.push(sd);
+ }
+ }
+
+ public void send(long data)
+ {
+ if (isPlayer() && blnWorking && !blnIsClosing)
+ {
+ SendData sd = new SendData(data);
+ qMessage.push(sd);
+ }
+ }*/
+ public void updateInfo() {
+ try {
+ String strResult;
+ strResult = hp + "\n";
+ strResult += (maxhp + hpbon) + "\n";
+ strResult += mp + "\n";
+ strResult += (maxmp + mpbon) + "\n";
+ send(MessageType.UpdateStats, strResult);
+ } catch (Exception e) {
+ game.log.printError("updateInfo():" + name + " disconnected", e);
+ isStopped = true;
+ }
+ }
+
+ public void updateRange() {
+ try {
+ String strResult = "" + (char) 28;
+ strResult += getRangeWithBonus() + "\n";
+ send(strResult);
+ } catch (Exception e) {
+ game.log.printError("updateRange():" + name + " disconnected", e);
+ }
+ }
+
+ public void updateItems() {
+ try {
+ StringBuilder sb = new StringBuilder();
+
+ for (LinkedList<Item> qStore : itemList.values()) {
+ if (qStore.size() > 0) {
+ Item itmStore = (Item) qStore.element();
+ if (itmStore.isArmor()) {
+ sb.append((2 + itmStore.intKind) + "\n");
+ } else if (itmStore.isWeapon()) {
+ sb.append("1\n");
+ } else {
+ sb.append("0\n");
+ }
+ sb.append(itmStore.name + "\n");
+ }
+ }
+ sb.append(".\n");
+ send(MessageType.UpdateItems, sb.toString());
+ if (game.overMerchant(x, y) != null) {
+ updateSell();
+ }
+ if (game.overPlayerMerchant(x, y) != null) {
+ updateSell();
+ }
+ } catch (Exception e) {
+ game.log.printError("updateItems():" + name + " disconnected", e);
+ isStopped = true;
+ }
+ isSaveNeeded = true;
+ }
+
+ public void updateStats() {
+ SpellGroup grpStore;
+ int i,
+ i2;
+
+ // FIXME: wtf, duplicated shit code again
+ // FIXME: convert to stringbuilder
+ try {
+ String strResult = "";
+ strResult += cash + " gp\n";
+ strResult += exp + " exp\n";
+ if (strebon == 0) {
+ strResult += "str: " + stre + "\n";
+ } else {
+ strResult += "str: " + stre + " + " + strebon + "\n";
+ }
+ if (intebon == 0) {
+ strResult += "int: " + inte + "\n";
+ } else {
+ strResult += "int: " + inte + " + " + intebon + "\n";
+ }
+ if (dextbon == 0) {
+ strResult += "dex: " + dext + "\n";
+ } else {
+ strResult += "dex: " + dext + " + " + dextbon + "\n";
+ }
+ if (consbon == 0) {
+ strResult += "con: " + cons + "\n";
+ } else {
+ strResult += "con: " + cons + " + " + consbon + "\n";
+ }
+ if (wisdbon == 0) {
+ strResult += "wis: " + wisd + "\n";
+ } else {
+ strResult += "wis: " + wisd + " + " + wisdbon + "\n";
+ }
+ if (dammodbon == 0) {
+ strResult += "DamMod: " + getDamMod() + "\n";
+ } else {
+ strResult += "DamMod: " + getDamMod() + " + " + dammodbon + "\n";
+ }
+ if (acbon == 0) {
+ strResult += "AC: " + getArmorMod() + "\n\n";
+ } else {
+ strResult += "AC: " + getArmorMod() + " + " + acbon + "\n";
+ }
+ strResult += "-Affected by-\n";
+ for (Condition cond : conditions) {
+ if (cond.display) {
+ strResult += cond.name + "\n";
+ }
+ }
+ strResult += "-Skills-\n";
+ for (Ability skill : skillMap.values()) {
+ strResult += skill.name + ": " + skill.getAbility() + "\n";
+ }
+ strResult += "-Spells-\n";
+ for (Ability spell : spellMap.values()) {
+ grpStore = game.getSpellGroup(spell.name);
+ if (grpStore != null) {
+ strResult += spell.name + ": " + spell.getAbility() + "\n";
+ strResult += grpStore.spellList(spell.getAbility());
+ }
+ }
+ if (master != null) {
+ strResult += "\nFollowing: " + master.name + "\n";
+ }
+ if (following != null) {
+ strResult += "\nFollowed By: " + following.name + "\n";
+ if (following.isPet()) {
+ strResult += following.hp + "/" + following.maxhp + " hp\n";
+ strResult += following.mp + "/" + following.maxmp + " mp\n";
+ strResult += following.cash + " gp\n";
+ strResult += following.exp + " exp\n";
+ if (following.strebon == 0) {
+ strResult += "str: " + following.stre + "\n";
+ } else {
+ strResult += "str: " + following.stre + " + " + following.strebon + "\n";
+ }
+ if (following.intebon == 0) {
+ strResult += "int: " + following.inte + "\n";
+ } else {
+ strResult += "int: " + following.inte + " + " + following.intebon + "\n";
+ }
+ if (following.dextbon == 0) {
+ strResult += "dex: " + following.dext + "\n";
+ } else {
+ strResult += "dex: " + following.dext + " + " + following.dextbon + "\n";
+ }
+ if (following.consbon == 0) {
+ strResult += "con: " + following.cons + "\n";
+ } else {
+ strResult += "con: " + following.cons + " + " + following.consbon + "\n";
+ }
+ if (following.wisdbon == 0) {
+ strResult += "wis: " + following.wisd + "\n";
+ } else {
+ strResult += "wis: " + following.wisd + " + " + following.wisdbon + "\n";
+ }
+ if (following.dammodbon == 0) {
+ strResult += "DamMod: " + following.getDamMod() + "\n";
+ } else {
+ strResult += "DamMod: " + following.getDamMod() + " + " + following.dammodbon + "\n";
+ }
+ if (following.acbon == 0) {
+ strResult += "AC: " + following.getArmorMod() + "\n\n";
+ } else {
+ strResult += "AC: " + following.getArmorMod() + " + " + following.acbon + "\n";
+ }
+ strResult += "-Affected by-\n";
+ for (Condition cndStore : following.conditions) {
+ if (cndStore.display) {
+ strResult += cndStore.name + "\n";
+ }
+ }
+ strResult += "-Skills-\n";
+ for (Ability skill : following.skillMap.values()) {
+ strResult += skill.name + ": " + skill.getAbility() + "\n";
+ }
+ strResult += "-Spells-\n";
+ for (Ability spell : following.skillMap.values()) {
+ grpStore = game.getSpellGroup(spell.name);
+ if (grpStore != null) {
+ strResult += spell.name + ": " + spell.getAbility() + "\n";
+ strResult += grpStore.spellList(spell.getAbility());
+ }
+ }
+ }
+ }
+ strResult += ".\n";
+ send(MessageType.UpdateInfo, strResult);
+ } catch (Exception e) {
+ game.log.printError("updateStats():" + name + " disconnected", e);
+ isStopped = true;
+ }
+ //updateRange();
+ isSaveNeeded = true;
+ }
+
+ public void halt() {
+ isHalted = true;
+ try {
+ send(MessageType.Halt, "");
+ } catch (Exception e) {
+ isHalted = false;
+ game.log.printError("halt()", e);
+ }
+ }
+
+ public void proceed() {
+ isHalted = false;
+ try {
+ send(MessageType.Proceed, ID + "\n");
+ } catch (Exception e) {
+ game.log.printError("proceed()", e);
+ }
+ }
+
+ public void stillThere() {
+ try {
+ send("" + (char) 13);
+ } catch (Exception e) {
+ game.log.printError("stillThere()", e);
+ }
+ }
+
+ public void resizeMap() {
+ int i, i2;
+ String strResult = (char) 19 + "";
+ strResult += game.mapsize + "\n";
+ send(strResult);
+ }
+
+ public void updateSell() {
+ StringBuilder sb = new StringBuilder();
+
+ for (LinkedList<Item> list : itemList.values()) {
+ for (Item item : list) {
+ sb.append(item.intCost / 2).append("gp)").append(item.name).append("\n");
+ }
+ }
+ sb.append(".\n");
+ send(MessageType.UpdateSell, sb.toString());
+ }
+
+ void offMerchant() {
+ send(MessageType.ExitMerchant, "");
+ }
+
+ private class SendThread extends Thread {
+
+ public SendThread() {
+ }
+
+ public void run() {
+ ServerMessage msg;
+ while (!isStopped) {
+ try {
+ msg = messageQueue.take();
+ try {
+ msg.send(outstream);
+ outstream.flush();
+ } catch (IOException e) {
+ game.log.printError("SendThread.run():" + msg + " to " + name, e);
+ isWorking = false;
+ isStopped = true;
+ close();
+ }
+ } catch (InterruptedException ex) {
+ Logger.getLogger(SendThread.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - modernised java.
+ */
+package duskz.server.entity;
+
+import duskz.server.DuskEngine;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Merchant represents a non-mobile entity where players can buy/sell items and
+ * pets or train.
+ *
+ * @author Tom Weingarten
+ */
+public class Merchant extends DuskObject {
+
+ DuskEngine engGame;
+ public final List<String> items = new ArrayList<>();
+
+ public Merchant(DuskEngine inGame) {
+ super(inGame.getID(), "Merchant");
+ engGame = inGame;
+ }
+
+ @Override
+ public int getImage() {
+ return engGame.merchantimage;
+ }
+
+ @Override
+ public byte getType() {
+ return MERCHANT;
+ }
+
+ @Override
+ public int getEntityType() {
+ return 2;
+ }
+
+ public boolean contains(String item) {
+ return items.contains(item);
+ }
+
+ public void remove(String item) {
+ items.remove(item);
+ }
+
+ public void pet(LivingThing thnMaster) {
+ try {
+ if (thnMaster.following != null && thnMaster.following.isPet()) {
+ thnMaster.chatMessage("You are only allowed 1 pet.");
+ return;
+ }
+ if (thnMaster.cash >= engGame.petcost) {
+ thnMaster.cash -= engGame.petcost;
+ } else {
+ thnMaster.chatMessage("You can't afford a pet.");
+ return;
+ }
+ if (thnMaster.isPet()) {
+ thnMaster.chatMessage("You ARE a pet!");
+ return;
+ }
+ thnMaster.halt();
+ thnMaster.chatMessage("Enter a name for your pet:");
+ String strName = thnMaster.instream.readLine().trim();
+ File filCheck = new File("pets/" + strName.toLowerCase());
+ File filCheck2 = new File("users/" + strName.toLowerCase());
+ while (filCheck.exists() || filCheck2.exists()
+ || !engGame.isGoodName(strName)) {
+ thnMaster.chatMessage("That name is already taken or has invalid characters, please enter another:");
+ strName = thnMaster.instream.readLine().trim();
+ filCheck = new File("pets/" + strName.toLowerCase());
+ filCheck2 = new File("users/" + strName.toLowerCase());
+ }
+ thnMaster.chatMessage("Choose a type of pet:");
+ File filPetTypes = new File("defPets");
+ String strList[] = filPetTypes.list();
+ for (int i = 0; i < strList.length; i++) {
+ thnMaster.chatMessage(strList[i]);
+ }
+ String strStore = thnMaster.instream.readLine().trim();
+ filCheck = new File("defPets/" + strStore);
+ while (strStore.equals("") || !filCheck.exists()) {
+ thnMaster.chatMessage("That is not a valid pet type:");
+ strStore = thnMaster.instream.readLine().trim();
+ filCheck = new File("defPets/" + strStore);
+ }
+ thnMaster.following = new LivingThing(strName, strStore, thnMaster, engGame);
+ } catch (Exception e) {
+ engGame.log.printError("Merchant.pet()", e);
+ } finally {
+ thnMaster.proceed();
+ }
+ }
+
+ public void train(String how, int quantity, LivingThing lt) {
+ quantity = Math.min(quantity, 100);
+
+ if (lt.exp < engGame.traincost * quantity) {
+ lt.chatMessage("Sorry, you don't have enough experience points.");
+ return;
+ }
+
+ switch (how.toLowerCase()) {
+ case "hp":
+ lt.exp -= engGame.traincost * quantity;
+ lt.maxhp += 10 * quantity;
+ lt.hp += 10 * quantity;
+ lt.updateInfo();
+ break;
+ case "mp":
+ lt.exp -= engGame.traincost * quantity;
+ lt.maxmp += 10 * quantity;
+ lt.mp += 10 * quantity;
+ lt.updateInfo();
+ break;
+ case "strength":
+ if (lt.stre + quantity > lt.stre_limit) {
+ quantity = lt.stre_limit - lt.stre;
+ }
+ lt.exp -= engGame.traincost * quantity;
+ lt.stre += quantity;
+ break;
+ case "intelligence":
+ if (lt.inte + quantity > lt.inte_limit) {
+ quantity = lt.inte_limit - lt.inte;
+ }
+ lt.exp -= engGame.traincost * quantity;
+ lt.inte += quantity;
+ break;
+ case "wisdom":
+ if (lt.wisd + quantity > lt.wisd_limit) {
+ quantity = lt.wisd_limit - lt.wisd;
+ }
+ lt.exp -= engGame.traincost * quantity;
+ lt.wisd += quantity;
+ break;
+ case "constitution":
+ if (lt.cons + quantity > lt.cons_limit) {
+ quantity = lt.cons_limit - lt.cons;
+ }
+ lt.exp -= engGame.traincost * quantity;
+ lt.cons += quantity;
+ break;
+ case "dexterity":
+ if (lt.dext + quantity > lt.dext_limit) {
+ quantity = lt.dext_limit - lt.dext;
+ }
+ lt.exp -= engGame.traincost * quantity;
+ lt.dext += quantity;
+ break;
+ default:
+ int skillLeft = 100 - lt.getSkill(how);
+ if (quantity > skillLeft) {
+ quantity = skillLeft;
+ }
+ if (lt.addToSkill(how, (byte) quantity)) {
+ lt.exp -= quantity * engGame.traincost;
+ } else {
+ return;
+ }
+ }
+ lt.updateStats();
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - modernised java, script wrapper,
+ * loader function.
+ */
+package duskz.server.entity;
+
+import duskz.server.Condition;
+import duskz.server.DuskEngine;
+import duskz.server.Faction;
+import duskz.server.GiveItem;
+import duskz.server.ItemList;
+import duskz.server.Log;
+import duskz.server.Script;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Mob(mobile) is the class of non-player moving entities.
+ *
+ * @author Tom Weingarten
+ */
+public class Mob extends LivingThing {
+
+ final public List<GiveItem> vctGiveItems = new ArrayList<>();
+ //Mob level
+ public int level = -1;
+ //AI
+ public double dblBravery = 0, //0 to 1, -1 makes mob always flee
+ dblGroupRelation = 0; //-1 to 1
+ public String strOnBattle = null;
+ //Faction
+ public Faction fctFaction;
+ public boolean blnOneUse = false;
+ public boolean blnCanSeePlayer = false;
+
+ //new Mob
+ public Mob(String strType, int locx, int locy, DuskEngine inEngine)
+ throws Exception {
+ super(inEngine.getID(), strType);
+ noChannel = -1;
+ game = inEngine;
+ Type = 1;
+ race = strType;
+ x = locx;
+ y = locy;
+ originalX = x;
+ originalY = y;
+ wornItems = new Equipment();
+ itemList = new ItemList();
+ battle = null;
+ loadMobFile(new File("defMobs/" + strType));
+ hp = maxhp;
+ mp = maxmp;
+ isSleeping = false;
+ isLoaded = true;
+ }
+
+ //new Mob w/ levels (provided for pre-2.3 compatibility)
+ public Mob(String strType, int level, int locx, int locy, DuskEngine inEngine)
+ throws Exception {
+ super(inEngine.getID(), strType);
+ noChannel = -1;
+ game = inEngine;
+ Type = 1;
+ race = strType;
+ x = locx;
+ y = locy;
+ originalX = x;
+ originalY = y;
+ wornItems = new Equipment();
+ itemList = new ItemList();
+ battle = null;
+ this.level = level;
+ loadMobFile(new File("defMobs/" + strType));
+ maxhp = maxhp * level;
+ maxmp = maxmp * level;
+ stre = stre * level;
+ inte = inte * level;
+ wisd = wisd * level;
+ dext = dext * level;
+ cons = cons * level;
+ hp = maxhp * level;
+ mp = maxmp * level;
+ isSleeping = false;
+ isLoaded = true;
+ }
+
+ @Override
+ public void leaveBattle() {
+ super.leaveBattle();
+ if (blnOneUse) {
+ game.removeDuskObject(this);
+ } else {
+ game.mobKilled(this);
+ // FIXME: need a game.mobKilled() function
+ // FIXME: this magic number is used in TickThread and DuskEngine
+ x = -6;
+ y = -6;
+ hp = game.mobrespawnspeed;//seconds till respawn
+ }
+ }
+
+ public void loadMobFile(File path) throws FileNotFoundException, IOException {
+ String line;
+ try (RandomAccessFile file = new RandomAccessFile(path, "r")) {
+ while (!((line = file.readLine()) == null || line.equals("."))) {
+ try {
+ parseMobFile(file, line);
+ } catch (NumberFormatException x) {
+ throw new IOException("Problem parsing mob " + path + " on field " + line, x);
+ }
+ }
+ if (fctFaction == null) {
+ game.log.printMessage(Log.DEBUG, "no faction found for mob \"" + name + "\"");
+ }
+ }
+ }
+
+ private void parseMobFile(RandomAccessFile in, String strStore) throws IOException, NumberFormatException {
+ switch (strStore.toLowerCase()) {
+ case "skill":
+ strStore = in.readLine();
+ int value = Byte.parseByte(in.readLine());
+ addToSkill(strStore, value);
+ game.log.printMessage(Log.DEBUG, strStore + "=" + value);
+ break;
+ case "condition":
+ Condition cndStore = game.getCondition(in.readLine());
+ cndStore.ticksPast = Integer.parseInt(in.readLine());
+ cndStore.duration = Integer.parseInt(in.readLine());
+ addCondition(cndStore);
+ game.log.printMessage(Log.DEBUG, "condition \"" + cndStore.name + "\"");
+ break;
+ case "giveitem":
+ String strItem = in.readLine();
+ double dblChance = Double.valueOf(in.readLine()).doubleValue();
+ vctGiveItems.add(new GiveItem(strItem, dblChance));
+ game.log.printMessage(Log.DEBUG, name + " gives a \"" + strItem + "\" " + (100 * dblChance) + "% of the time.");
+ break;
+ case "item":
+ Item itmStore = game.getItem(in.readLine());
+ if (itmStore != null) {
+ itmStore.lngDurability = Long.parseLong(in.readLine());
+ itmStore.intUses = Integer.parseInt(in.readLine());
+ itemList.addElement(itmStore);
+ }
+ break;
+ case "clan":
+ clan = in.readLine();
+ break;
+ case "race":
+ race = in.readLine();
+ break;
+ case "title":
+ title = in.readLine();
+ break;
+ case "description":
+ description = in.readLine();
+ break;
+ case "x":
+ x = Integer.parseInt(in.readLine());
+ break;
+ case "y":
+ y = Integer.parseInt(in.readLine());
+ break;
+ case "maxhp":
+ maxhp = Integer.parseInt(in.readLine());
+ break;
+ case "maxmp":
+ maxmp = Integer.parseInt(in.readLine());
+ break;
+ case "stre":
+ stre = Integer.parseInt(in.readLine());
+ break;
+ case "inte":
+ inte = Integer.parseInt(in.readLine());
+ break;
+ case "dext":
+ dext = Integer.parseInt(in.readLine());
+ break;
+ case "cons":
+ cons = Integer.parseInt(in.readLine());
+ break;
+ case "wisd":
+ wisd = Integer.parseInt(in.readLine());
+ break;
+ case "image":
+ imageid = Integer.parseInt(in.readLine());
+ break;
+ case "bravery":
+ dblBravery = Double.valueOf(in.readLine()).doubleValue();
+ break;
+ case "grouprelation":
+ dblGroupRelation = Double.valueOf(in.readLine()).doubleValue();
+ break;
+ case "wield":
+ parseWear(in, Equipment.WIELD);
+ break;
+ case "arms":
+ parseWear(in, Equipment.ARMS);
+ break;
+ case "legs":
+ parseWear(in, Equipment.LEGS);
+ break;
+ case "torso":
+ parseWear(in, Equipment.TORSO);
+ break;
+ case "waist":
+ parseWear(in, Equipment.WAIST);
+ break;
+ case "neck":
+ parseWear(in, Equipment.NECK);
+ break;
+ case "skull":
+ parseWear(in, Equipment.SKULL);
+ break;
+ case "eyes":
+ parseWear(in, Equipment.EYES);
+ break;
+ case "hands":
+ parseWear(in, Equipment.HANDS);
+ break;
+ case "faction":
+ String strFaction = in.readLine();
+ fctFaction = game.getFaction(strFaction);
+ if (fctFaction != null) {
+ game.log.printMessage(Log.DEBUG, "faction=\"" + fctFaction.strName + "\"");
+ } else {
+ game.log.printMessage(Log.DEBUG, "no faction found for \"" + strFaction + "\"");
+ }
+ break;
+ case "onBattle":
+ strOnBattle = in.readLine();
+ break;
+ case "nofollow":
+ noFollow = true;
+ break;
+ }
+ // engGame.log.printError("parseMobFile():Parsing \"" + strStore + "\" from " + name + "'s file", e);
+ }
+
+ public void onBattle(DuskEngine engGame) {
+ Script.exec("scripts/" + strOnBattle, engGame, this);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server.entity;
+
+import duskz.server.DuskEngine;
+import duskz.server.ItemList;
+
+/**
+ * Merchant represents a non-mobile entity where This merchant holds/sells items
+ * for the player that owns it The owner can give and take items and gp from it.
+ * The merchant will only be able to sell items it has been given. And only the
+ * number it has been given.
+ *
+ * @author Wildern
+ */
+public class PlayerMerchant extends DuskObject {
+
+ DuskEngine engGame;
+ public ItemList vctItems;
+ // FIXME: not public!!
+ public long cash;
+ public String strOwner;
+
+ public PlayerMerchant(DuskEngine inGame) {
+ super(inGame.getID(), "Merchant");
+ engGame = inGame;
+ }
+
+ @Override
+ public int getImage() {
+ return engGame.merchantimage;
+ }
+
+ @Override
+ public byte getType() {
+ return PLAYER_MARCHANT;
+ }
+
+ @Override
+ public int getEntityType() {
+ return 2;
+ }
+
+ public long contains(String strStore) {
+ if (vctItems.contains(strStore)) {
+ return vctItems.get(strStore).size();
+ }
+ return 0;
+ }
+
+ public void add(Item itmStore) {
+ vctItems.addElement(itmStore);
+ }
+
+ public Item remove(String strStore) {
+ return vctItems.removeElement(strStore);
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server.entity;
+
+/**
+ * A Prop is an entity that cannot move or be used.
+ *
+ * @author Tom Weingarten
+ */
+public class Prop extends DuskObject {
+
+ public int intImage;
+
+ public Prop(long lngID, String name) {
+ super(lngID, name);
+ }
+
+ @Override
+ public int getImage() {
+ return intImage;
+ }
+
+ @Override
+ public byte getType() {
+ return PROP;
+ }
+
+ @Override
+ public int getEntityType() {
+ return 3;
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server.entity;
+
+import duskz.server.DuskEngine;
+
+/**
+ * Represents a sign object. A sign contains a string message and can be viewed
+ * by LivingThings.
+ *
+ * @author Tom Weingarten
+ */
+public class Sign extends DuskObject {
+
+ public String strMessage;
+ private final DuskEngine eng;
+
+ public Sign(DuskEngine eng, String name, String msg, int locx, int locy, long lngID) {
+ super(lngID, name);
+ strMessage = msg;
+ x = locx;
+ y = locy;
+ this.eng = eng;
+ }
+
+ @Override
+ public byte getType() {
+ return SIGN;
+ }
+
+ @Override
+ public int getImage() {
+ return eng.signimage;
+ }
+
+ @Override
+ public int getEntityType() {
+ return 3;
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ */
+package duskz.server.entity;
+
+import duskz.util.Maths;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.PriorityQueue;
+
+/**
+ * Low level map management and helpers
+ *
+ * @author notzed
+ */
+public class TileMap implements Iterable<TileMap.MapData> {
+
+ private int rows, cols;
+ /**
+ * Tile map
+ */
+ private short tiles[];
+ /**
+ * Entities, they are chained off each other for efficiency reasons
+ */
+ private DuskObject entities[];
+ /**
+ * privileges for each cell. This appears to be unimplemented in Dusk so
+ * isn't here either.
+ */
+ protected short privs[];
+ /**
+ * Ownership for each cell. This appears to be unimplemented in Dusk so
+ * isn't here either.
+ */
+ protected int owner[];
+ /**
+ * Flags for iterators
+ */
+ public final static int SKIP_START = 1;
+ public final static int SKIP_END = 2;
+
+ /**
+ * Create a new empty map of the given size
+ *
+ * @param cols
+ * @param rows
+ */
+ public TileMap(int cols, int rows) {
+ this.rows = rows;
+ this.cols = cols;
+
+ tiles = new short[rows * cols];
+ entities = new DuskObject[rows * cols];
+ }
+
+ public int getRows() {
+ return rows;
+ }
+
+ public int getCols() {
+ return cols;
+ }
+
+ public void saveMap(File path) throws IOException {
+ path.delete();
+ try (RandomAccessFile rafFile = new RandomAccessFile(path, "rw")) {
+ rafFile.writeInt(cols);
+ rafFile.writeInt(rows);
+ for (int x = 0; x < cols; x++) {
+ for (int y = 0; y < rows; y++) {
+ rafFile.writeShort(getTile(x, y));
+ }
+ }
+ }
+ }
+ public static final int FORMAT_BYTE = 0;
+ public static final int FORMAT_SHORT = 1;
+
+ // Map in row major format (i.e. more efficient)
+ public static TileMap loadMapX(File path) throws IOException {
+ TileMap map;
+
+ try (DataInputStream mapFile = new DataInputStream(new FileInputStream(path))) {
+ int cols = mapFile.readInt();
+ int rows = mapFile.readInt();
+ map = new TileMap(cols, rows);
+ for (int y = 0; y < rows; y++) {
+ for (int x = 0; x < cols; x++) {
+ map.setTile(x, y, mapFile.readShort());
+ }
+ }
+ }
+ return map;
+ }
+
+ public static TileMap loadMap(File path, int format) throws IOException {
+ TileMap map;
+
+ try (RandomAccessFile mapFile = new RandomAccessFile(path, "r")) {
+ int cols = mapFile.readInt();
+ int rows = mapFile.readInt();
+ map = new TileMap(cols, rows);
+ for (int x = 0; x < cols; x++) {
+ for (int y = 0; y < rows; y++) {
+ if (format == FORMAT_BYTE)
+ map.setTile(x, y, mapFile.readByte());
+ else
+ map.setTile(x, y, mapFile.readShort());
+ }
+ }
+ }
+ return map;
+ }
+
+ /**
+ * Create a new map
+ *
+ * @param newcols
+ * @param newrows
+ * @return
+ */
+ public synchronized void resize(int newcols, int newrows) {
+ short[] ntiles = new short[newcols * newrows];
+ DuskObject[] nentities = new DuskObject[newcols * newrows];
+
+ int rx = Math.min(newcols, cols);
+ int ry = Math.min(newrows, rows);
+
+ for (int y = 0; y < ry; y++) {
+ for (int x = 0; x < rx; x++) {
+ int indexa = x + y * cols;
+ int indexb = x + y * newcols;
+
+ ntiles[indexb] = tiles[indexa];
+ nentities[indexb] = entities[indexa];
+ }
+ }
+
+ tiles = ntiles;
+ entities = nentities;
+ cols = newcols;
+ rows = newrows;
+ }
+
+ public boolean inside(int x, int y) {
+ return x >= 0 && x < cols
+ && y >= 0 && y < rows;
+ }
+
+ public void setTile(int x, int y, int t) {
+ tiles[x + y * cols] = (short) t;
+ }
+
+ public short getTile(int x, int y) {
+ return tiles[x + y * cols];
+ }
+
+ public synchronized List<DuskObject> getEntities(int x, int y, List<DuskObject> list) {
+ if (list == null)
+ list = new ArrayList<>();
+
+ DuskObject o = entities[x + y * cols];
+ while (o != null) {
+ list.add(o);
+ o = o.getNext();
+ }
+ return list;
+ }
+
+ public synchronized void addEntity(DuskObject o) {
+ if (inside(o.x, o.y)) {
+ int index = o.x + o.y * cols;
+
+ entities[index] = DuskObject.append(entities[index], o);
+ }
+ }
+
+ public synchronized void removeEntity(DuskObject o) {
+ if (inside(o.x, o.y)) {
+ int index = o.x + o.y * cols;
+
+ entities[index] = DuskObject.remove(entities[index], o);
+ }
+ }
+
+ /**
+ * Get an iterable over a range - allows foreach support
+ *
+ * @param x0
+ * @param y0
+ * @param x1
+ * @param y1
+ * @return
+ */
+ public Iterable<MapData> range(int x0, int y0, int x1, int y1) {
+ return new MapIterable(x0, y0, x1, y1);
+ }
+
+ /**
+ * Get an iterable over a range with a given centre and radius
+ *
+ * @param x
+ * @param y
+ * @param radius
+ * @return
+ */
+ public Iterable<MapData> range(int x, int y, int radius) {
+ return new MapIterable(x - radius, y - radius, x + radius + 1, y + radius + 1);
+ }
+
+ /**
+ * Get an iterable which will iterate over the looking path
+ *
+ * @param sx
+ * @param sy
+ * @param ex
+ * @param ey
+ * @param flags SKIP_END, SKIP_START to skip end/start locations
+ * (UNIMPLEMENTED)
+ * @return
+ */
+ public Iterable<MapData> look(int sx, int sy, int ex, int ey, int flags) {
+ return new LookIterable(sx, sy, ex, ey, flags);
+ }
+
+ public Iterable<MapData> look(int sx, int sy, int ex, int ey) {
+ return new LookIterable(sx, sy, ex, ey, 0);
+ }
+
+ public Iterable<MoveData> move(int sx, int sy, int ex, int ey, int flags, MoveListener l) {
+ return new MoveIterable(sx, sy, ex, ey, flags, l);
+ }
+
+ private class MapIterable implements Iterable<MapData> {
+
+ int x0, y0, x1, y1;
+
+ public MapIterable(int x0, int y0, int x1, int y1) {
+ this.x0 = x0;
+ this.y0 = y0;
+ this.x1 = x1;
+ this.y1 = y1;
+ }
+
+ @Override
+ public Iterator<MapData> iterator() {
+ return new MapIterator(x0, y0, x1, y1);
+ }
+ }
+
+ private class LookIterable implements Iterable<MapData> {
+
+ int sx, sy, ex, ey;
+ int flags;
+
+ public LookIterable(int sx, int sy, int ex, int ey, int flags) {
+ this.sx = sx;
+ this.sy = sy;
+ this.ex = ex;
+ this.ey = ey;
+ this.flags = flags;
+ }
+
+ @Override
+ public Iterator<MapData> iterator() {
+ return new LookIterator(sx, sy, ex, ey, flags);
+ }
+ }
+
+ private class MoveIterable implements Iterable<MoveData> {
+
+ int sx, sy, ex, ey;
+ int flags;
+ MoveListener l;
+
+ public MoveIterable(int sx, int sy, int ex, int ey, int flags, MoveListener l) {
+ this.sx = sx;
+ this.sy = sy;
+ this.ex = ex;
+ this.ey = ey;
+ this.flags = flags;
+ this.l = l;
+ }
+
+ @Override
+ public Iterator<MoveData> iterator() {
+ return new MoveIterator(sx, sy, ex, ey, flags, l);
+ }
+ }
+
+ public Iterator<MapData> getIterator(int x0, int y0, int x1, int y1) {
+ return new MapIterator(x0, y0, x1, y1);
+ }
+
+ @Override
+ public Iterator<MapData> iterator() {
+ return getIterator(0, 0, cols, rows);
+ }
+
+ public class MapData {
+
+ public int x, y;
+ public final List<DuskObject> entities = new ArrayList<>();
+ public short tile;
+
+ protected void setData(int x, int y) {
+ this.x = x;
+ this.y = y;
+ this.entities.clear();
+ if (inside(x, y)) {
+ this.tile = getTile(x, y);
+ getEntities(x, y, this.entities);
+ } else {
+ this.tile = 0;
+ }
+ }
+ }
+
+ public class MoveData extends MapData {
+
+ public String direction;
+ }
+
+ private class MapIterator implements Iterator<MapData> {
+
+ int x0, y0, x1, y1;
+ int x, y;
+ MapData data = new MapData();
+
+ public MapIterator(int x0, int y0, int x1, int y1) {
+ this.x0 = Maths.clamp(x0, 0, cols);
+ this.y0 = Maths.clamp(y0, 0, rows);
+ this.x1 = Maths.clamp(x1, 0, cols);
+ this.y1 = Maths.clamp(y1, 0, rows);
+ this.x = -1;
+ this.y = -1;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return (x + 1) < x1
+ || (y + 1) < y1;
+ }
+
+ @Override
+ public MapData next() {
+ // FIXME: this needs to iterate in x first then y
+ if (x == -1) {
+ x = x0;
+ y = y0;
+ } else if (y + 1 < y1) {
+ y++;
+ } else {
+ y = y0;
+ x++;
+ }
+
+ data.setData(x, y);
+
+ return data;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+
+ /**
+ * Implements an iterator which follows a 'looking' path
+ *
+ * TODO: it should probably use Bresenhams line algorithm
+ */
+ private class LookIterator implements Iterator<MapData> {
+
+ int x, y;
+ final int sx, sy;
+ final int ex, ey;
+ int flags;
+ boolean there = false;
+ MapData data = new MapData();
+
+ public LookIterator(int sx, int sy, int ex, int ey, int flags) {
+ this.x = sx;
+ this.y = sy;
+ this.sx = sx;
+ this.sy = sy;
+ this.ex = ex;
+ this.ey = ey;
+ this.flags = flags;
+
+ diffx = Math.abs(ex - sx);
+ diffy = Math.abs(ey - sy);
+ stepx = Integer.signum(ex - sx);
+ stepy = Integer.signum(ey - sy);
+ err = diffx - diffy;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return !there;
+ }
+ // Bresenham algorithm data, from wikipedia
+ int diffx, diffy;
+ int stepx, stepy;
+ int err;
+
+ void lineStep() {
+ int e2 = 2 * err;
+ if (e2 > -diffy) {
+ err -= diffy;
+ x += stepx;
+ }
+ if (e2 < diffx) {
+ err += diffx;
+ y += stepy;
+ }
+ }
+
+ @Override
+ public MapData next() {
+ there = x == ex && y == ey;
+
+ // FIXME: impelement?
+ //if ((flags & SKIP_START) != 0 && sx == x && sy == y) {
+ // lineStep();
+ //}
+
+ data.setData(x, y);
+
+ if (!there) {
+ lineStep();
+ }
+ return data;
+ }
+
+ public MapData nextOld() {
+ there = x == ex && y == ey;
+
+ data.setData(x, y);
+
+ if (!there) {
+ int stepx = Integer.signum(ex - y);
+ int stepy = Integer.signum(ey - y);
+ int dx = Math.abs(ex - x);
+ int dy = Math.abs(ey - y);
+
+ if (dx > dy) {
+ x += stepx;
+ } else if (dx < dy) {
+ y += stepy;
+ } else {
+ x += stepx;
+ y += stepy;
+ }
+ }
+
+ return data;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+
+ public interface MoveListener {
+
+ public boolean canMoveto(MapData md);
+ }
+
+ /**
+ * Iterator for movement.
+ */
+ private static class MoveInfo implements Comparable<MoveInfo> {
+
+ int x, y;
+ float cost;
+ float estimate;
+ String direction;
+ MoveInfo parent;
+
+ public MoveInfo(int x, int y, float cost, String direction) {
+ this.x = x;
+ this.y = y;
+ this.cost = cost;
+ this.direction = direction;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ MoveInfo o = (MoveInfo) obj;
+
+ return x == o.x && y == o.y;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 59 * hash + this.x;
+ hash = 59 * hash + this.y;
+ return hash;
+ }
+
+ @Override
+ public int compareTo(MoveInfo o) {
+ return Float.compare(cost, o.cost);
+ }
+ }
+
+ /**
+ * An iterator which steps through the individual moves to get to a
+ * destination.
+ *
+ * Implemented using A* algorithm, so can handle obstructions.
+ *
+ * TODO: Limit the search space.
+ */
+ private class MoveIterator implements Iterator<MoveData> {
+
+ int x, y;
+ final int sx, sy;
+ final int ex, ey;
+ int flags;
+ boolean there = false;
+ private final MoveListener l;
+ // quick hack version
+ Iterator<MoveInfo> iterator;
+ MoveData data = new MoveData();
+
+ public MoveIterator(int sx, int sy, int ex, int ey, int flags, MoveListener l) {
+ this.x = sx;
+ this.y = sy;
+ this.sx = sx;
+ this.sy = sy;
+ this.ex = ex;
+ this.ey = ey;
+ this.flags = flags;
+ this.l = l;
+
+ // A* requires the whole path to be calculated ahead of time.
+
+ List<MoveInfo> path = findPath();
+
+ System.out.printf("Finding path from %d,%d to %d,%d: ", sx, sy, ex, ey);
+
+ if (path != null) {
+ for (MoveInfo mi : path) {
+ System.out.print(" ");
+ System.out.print(mi.direction);
+ }
+ System.out.println();
+
+ if (!path.isEmpty() && (flags & SKIP_END) != 0) {
+ path.remove(path.size() - 1);
+ }
+
+ iterator = path.iterator();
+ } else {
+ System.out.println("No path found!");
+ }
+ }
+
+ float estimateCost(int sx, int sy, int ex, int ey) {
+ return (float) Math.sqrt((ex - sx) * (ex - sx) + (ey - sy) * (ey - sy));
+ }
+
+ List<MoveInfo> constructPath(List<MoveInfo> list, MoveInfo n) {
+ if (list == null)
+ list = new ArrayList<>();
+
+ if (n.parent != null) {
+ constructPath(list, n.parent);
+ list.add(n);
+ }
+
+ return list;
+ }
+
+ void moveIf(List<MoveInfo> list, int x, int y, float cost, String dir) {
+ data.setData(x, y);
+
+ if (l.canMoveto(data)) {
+ list.add(new MoveInfo(x, y, cost + 1, dir));
+ }
+ }
+
+ List<MoveInfo> getNeighbours(MoveInfo n) {
+ List<MoveInfo> list = new ArrayList<>(4);
+
+ moveIf(list, n.x + 1, n.y, n.cost, "e");
+ moveIf(list, n.x - 1, n.y, n.cost, "w");
+ moveIf(list, n.x, n.y + 1, n.cost, "s");
+ moveIf(list, n.x, n.y - 1, n.cost, "n");
+
+ return list;
+ }
+
+ // A* algorithm from here:
+ //http://www.peachpit.com/articles/article.aspx?p=101142&seqNum=2
+ public List<MoveInfo> findPath() {
+
+ PriorityQueue<MoveInfo> openList = new PriorityQueue();
+ HashSet<MoveInfo> closedList = new HashSet<>();
+
+ MoveInfo startNode = new MoveInfo(sx, sy, 0, null);
+ startNode.estimate = estimateCost(sx, sy, ex, ey);
+ startNode.parent = null;
+ openList.add(startNode);
+
+ while (!openList.isEmpty()) {
+ MoveInfo node = openList.poll();
+ if (node.x == ex && node.y == ey) {
+ // construct the path from start to goal
+ return constructPath(null, node);
+ }
+
+ List<MoveInfo> neighbors = getNeighbours(node);
+ for (int i = 0; i < neighbors.size(); i++) {
+ MoveInfo nnode = neighbors.get(i);
+ boolean isOpen = openList.contains(nnode);
+ boolean isClosed = closedList.contains(nnode);
+ float costFromStart = node.cost + 1;
+
+ // check if the neighbor node has not been
+ // traversed or if a shorter path to this
+ // neighbor node is found.
+ if ((!isOpen && !isClosed)
+ || costFromStart < nnode.cost) {
+ nnode.parent = node;
+ nnode.cost = costFromStart;
+ nnode.estimate = estimateCost(nnode.x, nnode.y, ex, ey);
+ if (isClosed) {
+ closedList.remove(nnode);
+ }
+ if (!isOpen) {
+ openList.add(nnode);
+ }
+ }
+ }
+ closedList.add(node);
+ }
+
+ // no path found
+ return null;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (iterator != null)
+ return iterator.hasNext();
+ else
+ return false;
+ }
+
+ @Override
+ public MoveData next() {
+ MoveInfo mi = iterator.next();
+
+ data.setData(mi.x, mi.y);
+ data.direction = mi.direction;
+
+ return data;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+ }
+
+ public static void main(String[] args) {
+ TileMap map = new TileMap(16, 16);
+
+ /*
+ for (MapData md : map.look(5, 5, 10, 3)) {
+ System.out.printf(" %d,%d\n", md.x, md.y);
+ }
+ for (MapData md : map.look(15, 15, 0, 0)) {
+ System.out.printf(" %d,%d\n", md.x, md.y);
+ }
+ for (MapData md : map.look(15, 0, 0, 15)) {
+ System.out.printf(" %d,%d\n", md.x, md.y);
+ }*/
+
+
+ MoveListener l = new MoveListener() {
+ @Override
+ public boolean canMoveto(MapData md) {
+ //System.out.printf("can move %d,%d\n", md.x, md.y);
+ return md.tile == 0;
+ }
+ };
+ System.out.println("no obstacles");
+ for (MoveData md : map.move(0, 0, 10, 10, 0, l)) {
+ System.out.printf(" %d,%d %s\n", md.x, md.y, md.direction);
+ }
+
+ // put an obstacle in the way
+ for (int x = 0; x < 11; x++) {
+ map.setTile(x, 5, 1);
+ }
+ System.out.println("line in the way");
+ for (MoveData md : map.move(0, 0, 10, 10, SKIP_END, l)) {
+ System.out.printf(" %d,%d %s\n", md.x, md.y, md.direction);
+ }
+ System.out.println("line in the way to last");
+ for (MoveData md : map.move(0, 0, 1, 1, 0, l)) {
+ System.out.printf(" %d,%d %s\n", md.x, md.y, md.direction);
+ }
+
+ }
+}
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is 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. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ 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.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ 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 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. Use with the GNU Affero General Public License.
+
+ 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 Affero 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 special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 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 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 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ 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 GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ 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
+this service 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.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+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
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE 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.
+
+ 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
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
--- /dev/null
+
+README
+------
+This is the client frontend to DuskZ, it uses JavaFX. It connects
+to the DuskServer togehter and requires some local data installed.
+
+It is a fork and major overhaul of the Dusk 2.7.3 source code, released
+circa 2000.
+
+Currently a recent Oracle JRE is required to execute this application.
+
+This is currently in an alpha state and in very active development.
+
+ ... to be completed ...
+
+INSTALLATION
+------------
+ ... to be completed ...
+
+RUNNING
+-------
+ ... to be completed ...
+
+LICENSE
+-------
+ DuskZ is free software, see COPYING for your rights.
+
+ Some files are under other compatible licenses.
+
+ Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+
+ DuskZ is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ DuskZ 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DuskZ. If not, see <http://www.gnu.org/licenses/>.
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?><!-- You may freely edit this file. See commented blocks below for --><!-- some examples of how to customize the build. --><!-- (If you delete it and reopen the project it will be recreated.) --><!-- By default, only the Clean and Build commands use this build script. --><project name="DuskZ" default="default" basedir="." xmlns:fx="javafx:com.sun.javafx.tools.ant">
+ <description>Builds, tests, and runs the project DuskZ.</description>
+ <import file="nbproject/build-impl.xml"/>
+ <!--
+
+ There exist several targets which are by default empty and which can be
+ used for execution of your tasks. These targets are usually executed
+ before and after some main targets. Those of them relevant for JavaFX project are:
+
+ -pre-init: called before initialization of project properties
+ -post-init: called after initialization of project properties
+ -pre-compile: called before javac compilation
+ -post-compile: called after javac compilation
+ -pre-compile-test: called before javac compilation of JUnit tests
+ -post-compile-test: called after javac compilation of JUnit tests
+ -pre-jfx-jar: called before FX SDK specific <fx:jar> task
+ -post-jfx-jar: called after FX SDK specific <fx:jar> task
+ -pre-jfx-deploy: called before FX SDK specific <fx:deploy> task
+ -post-jfx-deploy: called after FX SDK specific <fx:deploy> task
+ -pre-jfx-native: called just after -pre-jfx-deploy if <fx:deploy> runs in native packaging mode
+ -post-jfx-native: called just after -post-jfx-deploy if <fx:deploy> runs in native packaging mode
+ -post-clean: called after cleaning build products
+
+ (Targets beginning with '-' are not intended to be called on their own.)
+
+ Example of inserting a HTML postprocessor after javaFX SDK deployment:
+
+ <target name="-post-jfx-deploy">
+ <basename property="jfx.deployment.base" file="${jfx.deployment.jar}" suffix=".jar"/>
+ <property name="jfx.deployment.html" location="${jfx.deployment.dir}${file.separator}${jfx.deployment.base}.html"/>
+ <custompostprocess>
+ <fileset dir="${jfx.deployment.html}"/>
+ </custompostprocess>
+ </target>
+
+ Example of calling an Ant task from JavaFX SDK. Note that access to JavaFX SDK Ant tasks must be
+ initialized; to ensure this is done add the dependence on -check-jfx-sdk-version target:
+
+ <target name="-post-jfx-jar" depends="-check-jfx-sdk-version">
+ <echo message="Calling jar task from JavaFX SDK"/>
+ <fx:jar ...>
+ ...
+ </fx:jar>
+ </target>
+
+ For more details about JavaFX SDK Ant tasks go to
+ http://docs.oracle.com/javafx/2/deployment/jfxpub-deployment.htm
+
+ For list of available properties check the files
+ nbproject/build-impl.xml and nbproject/jfx-impl.xml.
+
+ -->
+</project>
--- /dev/null
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT ***
+*** EDIT ../build.xml INSTEAD ***
+
+For the purpose of easier reading the script
+is divided into following sections:
+
+ - initialization
+ - compilation
+ - jar
+ - execution
+ - debugging
+ - javadoc
+ - test compilation
+ - test execution
+ - test debugging
+ - applet
+ - cleanup
+
+ -->
+<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="DuskZ-impl">
+ <import file="jfx-impl.xml"/>
+ <fail message="Please build using Ant 1.8.0 or higher.">
+ <condition>
+ <not>
+ <antversion atleast="1.8.0"/>
+ </not>
+ </condition>
+ </fail>
+ <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
+ <!--
+ ======================
+ INITIALIZATION SECTION
+ ======================
+ -->
+ <target name="-pre-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="-pre-init" name="-init-private">
+ <property file="nbproject/private/config.properties"/>
+ <property file="nbproject/private/configs/${config}.properties"/>
+ <property file="nbproject/private/private.properties"/>
+ </target>
+ <target depends="-pre-init,-init-private" name="-init-user">
+ <property file="${user.properties.file}"/>
+ <!-- The two properties below are usually overridden -->
+ <!-- by the active platform. Just a fallback. -->
+ <property name="default.javac.source" value="1.4"/>
+ <property name="default.javac.target" value="1.4"/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user" name="-init-project">
+ <property file="nbproject/configs/${config}.properties"/>
+ <property file="nbproject/project.properties"/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
+ <j2seproject1:property name="platform.home" value="platforms.${platform.active}.home"/>
+ <j2seproject1:property name="platform.bootcp" value="platforms.${platform.active}.bootclasspath"/>
+ <j2seproject1:property name="platform.compiler" value="platforms.${platform.active}.compile"/>
+ <j2seproject1:property name="platform.javac.tmp" value="platforms.${platform.active}.javac"/>
+ <condition property="platform.javac" value="${platform.home}/bin/javac">
+ <equals arg1="${platform.javac.tmp}" arg2="$${platforms.${platform.active}.javac}"/>
+ </condition>
+ <property name="platform.javac" value="${platform.javac.tmp}"/>
+ <j2seproject1:property name="platform.java.tmp" value="platforms.${platform.active}.java"/>
+ <condition property="platform.java" value="${platform.home}/bin/java">
+ <equals arg1="${platform.java.tmp}" arg2="$${platforms.${platform.active}.java}"/>
+ </condition>
+ <property name="platform.java" value="${platform.java.tmp}"/>
+ <j2seproject1:property name="platform.javadoc.tmp" value="platforms.${platform.active}.javadoc"/>
+ <condition property="platform.javadoc" value="${platform.home}/bin/javadoc">
+ <equals arg1="${platform.javadoc.tmp}" arg2="$${platforms.${platform.active}.javadoc}"/>
+ </condition>
+ <property name="platform.javadoc" value="${platform.javadoc.tmp}"/>
+ <condition property="platform.invalid" value="true">
+ <or>
+ <contains string="${platform.javac}" substring="$${platforms."/>
+ <contains string="${platform.java}" substring="$${platforms."/>
+ <contains string="${platform.javadoc}" substring="$${platforms."/>
+ </or>
+ </condition>
+ <fail unless="platform.home">Must set platform.home</fail>
+ <fail unless="platform.bootcp">Must set platform.bootcp</fail>
+ <fail unless="platform.java">Must set platform.java</fail>
+ <fail unless="platform.javac">Must set platform.javac</fail>
+ <fail if="platform.invalid">
+ The J2SE Platform is not correctly set up.
+ Your active platform is: ${platform.active}, but the corresponding property "platforms.${platform.active}.home" is not found in the project's properties files.
+ Either open the project in the IDE and setup the Platform with the same name or add it manually.
+ For example like this:
+ ant -Duser.properties.file=<path_to_property_file> jar (where you put the property "platforms.${platform.active}.home" in a .properties file)
+ or ant -Dplatforms.${platform.active}.home=<path_to_JDK_home> jar (where no properties file is used)
+ </fail>
+ <available file="${manifest.file}" property="manifest.available"/>
+ <condition property="splashscreen.available">
+ <and>
+ <not>
+ <equals arg1="${application.splash}" arg2="" trim="true"/>
+ </not>
+ <available file="${application.splash}"/>
+ </and>
+ </condition>
+ <condition property="main.class.available">
+ <and>
+ <isset property="main.class"/>
+ <not>
+ <equals arg1="${main.class}" arg2="" trim="true"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="manifest.available+main.class">
+ <and>
+ <isset property="manifest.available"/>
+ <isset property="main.class.available"/>
+ </and>
+ </condition>
+ <condition property="do.archive">
+ <not>
+ <istrue value="${jar.archive.disabled}"/>
+ </not>
+ </condition>
+ <condition property="do.mkdist">
+ <and>
+ <isset property="do.archive"/>
+ <isset property="libs.CopyLibs.classpath"/>
+ <not>
+ <istrue value="${mkdist.disabled}"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="manifest.available+main.class+mkdist.available">
+ <and>
+ <istrue value="${manifest.available+main.class}"/>
+ <isset property="do.mkdist"/>
+ </and>
+ </condition>
+ <condition property="do.archive+manifest.available">
+ <and>
+ <isset property="manifest.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="do.archive+main.class.available">
+ <and>
+ <isset property="main.class.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="do.archive+splashscreen.available">
+ <and>
+ <isset property="splashscreen.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="do.archive+manifest.available+main.class">
+ <and>
+ <istrue value="${manifest.available+main.class}"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="manifest.available-mkdist.available">
+ <or>
+ <istrue value="${manifest.available}"/>
+ <isset property="do.mkdist"/>
+ </or>
+ </condition>
+ <condition property="manifest.available+main.class-mkdist.available">
+ <or>
+ <istrue value="${manifest.available+main.class}"/>
+ <isset property="do.mkdist"/>
+ </or>
+ </condition>
+ <condition property="have.tests">
+ <or>
+ <available file="${test.src.dir}"/>
+ </or>
+ </condition>
+ <condition property="have.sources">
+ <or>
+ <available file="${src.dir}"/>
+ </or>
+ </condition>
+ <condition property="netbeans.home+have.tests">
+ <and>
+ <isset property="netbeans.home"/>
+ <isset property="have.tests"/>
+ </and>
+ </condition>
+ <condition property="no.javadoc.preview">
+ <and>
+ <isset property="javadoc.preview"/>
+ <isfalse value="${javadoc.preview}"/>
+ </and>
+ </condition>
+ <property name="run.jvmargs" value=""/>
+ <property name="run.jvmargs.ide" value=""/>
+ <property name="javac.compilerargs" value=""/>
+ <property name="work.dir" value="${basedir}"/>
+ <condition property="no.deps">
+ <and>
+ <istrue value="${no.dependencies}"/>
+ </and>
+ </condition>
+ <property name="javac.debug" value="true"/>
+ <property name="javadoc.preview" value="true"/>
+ <property name="application.args" value=""/>
+ <property name="source.encoding" value="${file.encoding}"/>
+ <property name="runtime.encoding" value="${source.encoding}"/>
+ <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
+ <and>
+ <isset property="javadoc.encoding"/>
+ <not>
+ <equals arg1="${javadoc.encoding}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <property name="javadoc.encoding.used" value="${source.encoding}"/>
+ <property name="includes" value="**"/>
+ <property name="excludes" value=""/>
+ <property name="do.depend" value="false"/>
+ <condition property="do.depend.true">
+ <istrue value="${do.depend}"/>
+ </condition>
+ <path id="endorsed.classpath.path" path="${endorsed.classpath}"/>
+ <condition else="" property="endorsed.classpath.cmd.line.arg" value="-Xbootclasspath/p:'${toString:endorsed.classpath.path}'">
+ <length length="0" string="${endorsed.classpath}" when="greater"/>
+ </condition>
+ <property name="jar.index" value="false"/>
+ <property name="jar.index.metainf" value="${jar.index}"/>
+ <property name="copylibs.rebase" value="true"/>
+ <available file="${meta.inf.dir}/persistence.xml" property="has.persistence.xml"/>
+ <condition property="junit.available">
+ <or>
+ <available classname="org.junit.Test" classpath="${run.test.classpath}"/>
+ <available classname="junit.framework.Test" classpath="${run.test.classpath}"/>
+ </or>
+ </condition>
+ <condition property="testng.available">
+ <available classname="org.testng.annotations.Test" classpath="${run.test.classpath}"/>
+ </condition>
+ <condition property="junit+testng.available">
+ <and>
+ <istrue value="${junit.available}"/>
+ <istrue value="${testng.available}"/>
+ </and>
+ </condition>
+ <condition else="testng" property="testng.mode" value="mixed">
+ <istrue value="${junit+testng.available}"/>
+ </condition>
+ <condition else="" property="testng.debug.mode" value="-mixed">
+ <istrue value="${junit+testng.available}"/>
+ </condition>
+ </target>
+ <target name="-post-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-check-javafx" name="-init-check">
+ <fail unless="src.dir">Must set src.dir</fail>
+ <fail unless="test.src.dir">Must set test.src.dir</fail>
+ <fail unless="build.dir">Must set build.dir</fail>
+ <fail unless="dist.dir">Must set dist.dir</fail>
+ <fail unless="build.classes.dir">Must set build.classes.dir</fail>
+ <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
+ <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
+ <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
+ <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
+ <fail unless="dist.jar">Must set dist.jar</fail>
+ </target>
+ <target name="-init-macrodef-property">
+ <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute name="name"/>
+ <attribute name="value"/>
+ <sequential>
+ <property name="@{name}" value="${@{value}}"/>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors">
+ <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <attribute default="${javac.processorpath}" name="processorpath"/>
+ <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="${javac.debug}" name="debug"/>
+ <attribute default="${empty.dir}" name="sourcepath"/>
+ <attribute default="${empty.dir}" name="gensrcdir"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.dir}/empty" name="empty.dir"/>
+ <mkdir dir="${empty.dir}"/>
+ <mkdir dir="@{apgeneratedsrcdir}"/>
+ <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" executable="${platform.javac}" fork="yes" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+ <src>
+ <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </src>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <compilerarg line="${javac.compilerargs}"/>
+ <compilerarg value="-processorpath"/>
+ <compilerarg path="@{processorpath}:${empty.dir}"/>
+ <compilerarg line="${ap.processors.internal}"/>
+ <compilerarg line="${annotation.processing.processor.options}"/>
+ <compilerarg value="-s"/>
+ <compilerarg path="@{apgeneratedsrcdir}"/>
+ <compilerarg line="${ap.proc.none.internal}"/>
+ <customize/>
+ </javac>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-ap-cmdline-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal">
+ <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <attribute default="${javac.processorpath}" name="processorpath"/>
+ <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="${javac.debug}" name="debug"/>
+ <attribute default="${empty.dir}" name="sourcepath"/>
+ <attribute default="${empty.dir}" name="gensrcdir"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.dir}/empty" name="empty.dir"/>
+ <mkdir dir="${empty.dir}"/>
+ <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" executable="${platform.javac}" fork="yes" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+ <src>
+ <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </src>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <compilerarg line="${javac.compilerargs}"/>
+ <customize/>
+ </javac>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac">
+ <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <sequential>
+ <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ </depend>
+ </sequential>
+ </macrodef>
+ <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <sequential>
+ <fail unless="javac.includes">Must set javac.includes</fail>
+ <pathconvert pathsep="${line.separator}" property="javac.includes.binary">
+ <path>
+ <filelist dir="@{destdir}" files="${javac.includes}"/>
+ </path>
+ <globmapper from="*.java" to="*.class"/>
+ </pathconvert>
+ <tempfile deleteonexit="true" property="javac.includesfile.binary"/>
+ <echo file="${javac.includesfile.binary}" message="${javac.includes.binary}"/>
+ <delete>
+ <files includesfile="${javac.includesfile.binary}"/>
+ </delete>
+ <delete>
+ <fileset file="${javac.includesfile.binary}"/>
+ </delete>
+ </sequential>
+ </macrodef>
+ </target>
+ <target if="${junit.available}" name="-init-macrodef-junit-init">
+ <condition else="false" property="nb.junit.batch" value="true">
+ <and>
+ <istrue value="${junit.available}"/>
+ <not>
+ <isset property="test.method"/>
+ </not>
+ </and>
+ </condition>
+ <condition else="false" property="nb.junit.single" value="true">
+ <and>
+ <istrue value="${junit.available}"/>
+ <isset property="test.method"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-init-test-properties">
+ <property name="test.binaryincludes" value="<nothing>"/>
+ <property name="test.binarytestincludes" value=""/>
+ <property name="test.binaryexcludes" value=""/>
+ </target>
+ <target if="${nb.junit.single}" name="-init-macrodef-junit-single" unless="${nb.junit.batch}">
+ <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" jvm="${platform.java}" showoutput="true" tempdir="${build.dir}">
+ <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-test-properties" if="${nb.junit.batch}" name="-init-macrodef-junit-batch" unless="${nb.junit.single}">
+ <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" jvm="${platform.java}" showoutput="true" tempdir="${build.dir}">
+ <batchtest todir="${build.test.results.dir}">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
+ <filename name="${test.binarytestincludes}"/>
+ </fileset>
+ </batchtest>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit-init,-init-macrodef-junit-single, -init-macrodef-junit-batch" if="${junit.available}" name="-init-macrodef-junit"/>
+ <target if="${testng.available}" name="-init-macrodef-testng">
+ <macrodef name="testng" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <condition else="" property="testng.methods.arg" value="@{testincludes}.@{testmethods}">
+ <isset property="test.method"/>
+ </condition>
+ <union id="test.set">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ </union>
+ <taskdef classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}" name="testng"/>
+ <testng classfilesetref="test.set" failureProperty="tests.failed" jvm="${platform.java}" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="DuskZ" testname="TestNG tests" workingDir="${work.dir}">
+ <xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/>
+ <propertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </propertyset>
+ <customize/>
+ </testng>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-test-impl">
+ <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <echo>No tests executed.</echo>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit" if="${junit.available}" name="-init-macrodef-junit-impl">
+ <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <j2seproject3:junit excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize/>
+ </j2seproject3:junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-testng" if="${testng.available}" name="-init-macrodef-testng-impl">
+ <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <j2seproject3:testng excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize/>
+ </j2seproject3:testng>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-test-impl,-init-macrodef-junit-impl,-init-macrodef-testng-impl" name="-init-macrodef-test">
+ <macrodef name="test" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <sequential>
+ <j2seproject3:test-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ </customize>
+ </j2seproject3:test-impl>
+ </sequential>
+ </macrodef>
+ </target>
+ <target if="${junit.available}" name="-init-macrodef-junit-debug" unless="${nb.junit.batch}">
+ <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" jvm="${platform.java}" showoutput="true" tempdir="${build.dir}">
+ <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-test-properties" if="${nb.junit.batch}" name="-init-macrodef-junit-debug-batch">
+ <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" jvm="${platform.java}" showoutput="true" tempdir="${build.dir}">
+ <batchtest todir="${build.test.results.dir}">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
+ <filename name="${test.binarytestincludes}"/>
+ </fileset>
+ </batchtest>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit-debug,-init-macrodef-junit-debug-batch" if="${junit.available}" name="-init-macrodef-junit-debug-impl">
+ <macrodef name="test-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <j2seproject3:junit-debug excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize/>
+ </j2seproject3:junit-debug>
+ </sequential>
+ </macrodef>
+ </target>
+ <target if="${testng.available}" name="-init-macrodef-testng-debug">
+ <macrodef name="testng-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <element name="customize2" optional="true"/>
+ <sequential>
+ <condition else="-testclass @{testClass}" property="test.class.or.method" value="-methods @{testClass}.@{testMethod}">
+ <isset property="test.method"/>
+ </condition>
+ <condition else="-suitename DuskZ -testname @{testClass} ${test.class.or.method}" property="testng.cmd.args" value="@{testClass}">
+ <matches pattern=".*\.xml" string="@{testClass}"/>
+ </condition>
+ <delete dir="${build.test.results.dir}" quiet="true"/>
+ <mkdir dir="${build.test.results.dir}"/>
+ <j2seproject3:debug classname="org.testng.TestNG" classpath="${debug.test.classpath}">
+ <customize>
+ <customize2/>
+ <jvmarg value="-ea"/>
+ <arg line="${testng.debug.mode}"/>
+ <arg line="-d ${build.test.results.dir}"/>
+ <arg line="-listener org.testng.reporters.VerboseReporter"/>
+ <arg line="${testng.cmd.args}"/>
+ </customize>
+ </j2seproject3:debug>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-testng-debug" if="${testng.available}" name="-init-macrodef-testng-debug-impl">
+ <macrodef name="testng-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <element implicit="true" name="customize2" optional="true"/>
+ <sequential>
+ <j2seproject3:testng-debug testClass="@{testClass}" testMethod="@{testMethod}">
+ <customize2/>
+ </j2seproject3:testng-debug>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit-debug-impl" if="${junit.available}" name="-init-macrodef-test-debug-junit">
+ <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <sequential>
+ <j2seproject3:test-debug-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ </customize>
+ </j2seproject3:test-debug-impl>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-testng-debug-impl" if="${testng.available}" name="-init-macrodef-test-debug-testng">
+ <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <sequential>
+ <j2seproject3:testng-debug-impl testClass="@{testClass}" testMethod="@{testMethod}">
+ <customize2>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ </customize2>
+ </j2seproject3:testng-debug-impl>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-test-debug-junit,-init-macrodef-test-debug-testng" name="-init-macrodef-test-debug"/>
+ <!--
+ pre NB7.2 profiling section; consider it deprecated
+ -->
+ <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile, -profile-init-check" if="profiler.info.jvmargs.agent" name="profile-init"/>
+ <target if="profiler.info.jvmargs.agent" name="-profile-pre-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="profiler.info.jvmargs.agent" name="-profile-post-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="profiler.info.jvmargs.agent" name="-profile-init-macrodef-profile">
+ <macrodef name="resolve">
+ <attribute name="name"/>
+ <attribute name="value"/>
+ <sequential>
+ <property name="@{name}" value="${env.@{value}}"/>
+ </sequential>
+ </macrodef>
+ <macrodef name="profile">
+ <attribute default="${main.class}" name="classname"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property environment="env"/>
+ <resolve name="profiler.current.path" value="${profiler.info.pathvar}"/>
+ <java classname="@{classname}" dir="${profiler.info.dir}" fork="true" jvm="${profiler.info.jvm}">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg value="${profiler.info.jvmargs.agent}"/>
+ <jvmarg line="${profiler.info.jvmargs}"/>
+ <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
+ <arg line="${application.args}"/>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile" if="profiler.info.jvmargs.agent" name="-profile-init-check">
+ <fail unless="profiler.info.jvm">Must set JVM to use for profiling in profiler.info.jvm</fail>
+ <fail unless="profiler.info.jvmargs.agent">Must set profiler agent JVM arguments in profiler.info.jvmargs.agent</fail>
+ </target>
+ <!--
+ end of pre NB7.2 profiling section
+ -->
+ <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
+ <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${main.class}" name="name"/>
+ <attribute default="${debug.classpath}" name="classpath"/>
+ <attribute default="" name="stopclassname"/>
+ <sequential>
+ <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <bootclasspath>
+ <path path="${platform.bootcp}"/>
+ </bootclasspath>
+ </nbjpdastart>
+ </sequential>
+ </macrodef>
+ <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${build.classes.dir}" name="dir"/>
+ <sequential>
+ <nbjpdareload>
+ <fileset dir="@{dir}" includes="${fix.classes}">
+ <include name="${fix.includes}*.class"/>
+ </fileset>
+ </nbjpdareload>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-debug-args">
+ <exec executable="${platform.java}" outputproperty="version-output">
+ <arg value="-version"/>
+ </exec>
+ <condition property="have-jdk-older-than-1.4">
+ <or>
+ <contains string="${version-output}" substring="java version "1.0"/>
+ <contains string="${version-output}" substring="java version "1.1"/>
+ <contains string="${version-output}" substring="java version "1.2"/>
+ <contains string="${version-output}" substring="java version "1.3"/>
+ </or>
+ </condition>
+ <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
+ <istrue value="${have-jdk-older-than-1.4}"/>
+ </condition>
+ <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
+ <os family="windows"/>
+ </condition>
+ <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
+ <isset property="debug.transport"/>
+ </condition>
+ </target>
+ <target depends="-init-debug-args" name="-init-macrodef-debug">
+ <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="classname"/>
+ <attribute default="${debug.classpath}" name="classpath"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <java classname="@{classname}" dir="${work.dir}" fork="true" jvm="${platform.java}">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+ <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-java">
+ <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${main.class}" name="classname"/>
+ <attribute default="${run.classpath}" name="classpath"/>
+ <attribute default="jvm" name="jvm"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <java classname="@{classname}" dir="${work.dir}" fork="true" jvm="${platform.java}">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+ <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-copylibs">
+ <macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${manifest.file}" name="manifest"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <pathconvert property="run.classpath.without.build.classes.dir">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to=""/>
+ </pathconvert>
+ <pathconvert pathsep=" " property="jar.classpath">
+ <path path="${run.classpath.without.build.classes.dir}"/>
+ <chainedmapper>
+ <flattenmapper/>
+ <filtermapper>
+ <replacestring from=" " to="%20"/>
+ </filtermapper>
+ <globmapper from="*" to="lib/*"/>
+ </chainedmapper>
+ </pathconvert>
+ <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
+ <copylibs compress="${jar.compress}" index="${jar.index}" indexMetaInf="${jar.index.metainf}" jarfile="${dist.jar}" manifest="@{manifest}" rebase="${copylibs.rebase}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
+ <fileset dir="${build.classes.dir}"/>
+ <manifest>
+ <attribute name="Class-Path" value="${jar.classpath}"/>
+ <customize/>
+ </manifest>
+ </copylibs>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-presetdef-jar">
+ <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}">
+ <j2seproject1:fileset dir="${build.classes.dir}"/>
+ </jar>
+ </presetdef>
+ </target>
+ <target name="-init-ap-cmdline-properties">
+ <property name="annotation.processing.enabled" value="true"/>
+ <property name="annotation.processing.processors.list" value=""/>
+ <property name="annotation.processing.processor.options" value=""/>
+ <property name="annotation.processing.run.all.processors" value="true"/>
+ <property name="javac.processorpath" value="${javac.classpath}"/>
+ <property name="javac.test.processorpath" value="${javac.test.classpath}"/>
+ <condition property="ap.supported.internal" value="true">
+ <not>
+ <matches pattern="1\.[0-5](\..*)?" string="${javac.source}"/>
+ </not>
+ </condition>
+ </target>
+ <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-ap-cmdline-supported">
+ <condition else="" property="ap.processors.internal" value="-processor ${annotation.processing.processors.list}">
+ <isfalse value="${annotation.processing.run.all.processors}"/>
+ </condition>
+ <condition else="" property="ap.proc.none.internal" value="-proc:none">
+ <isfalse value="${annotation.processing.enabled}"/>
+ </condition>
+ </target>
+ <target depends="-init-ap-cmdline-properties,-init-ap-cmdline-supported" name="-init-ap-cmdline">
+ <property name="ap.cmd.line.internal" value=""/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-test,-init-macrodef-test-debug,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar,-init-ap-cmdline" name="init"/>
+ <!--
+ ===================
+ COMPILATION SECTION
+ ===================
+ -->
+ <target name="-deps-jar-init" unless="built-jar.properties">
+ <property location="${build.dir}/built-jar.properties" name="built-jar.properties"/>
+ <delete file="${built-jar.properties}" quiet="true"/>
+ </target>
+ <target if="already.built.jar.${basedir}" name="-warn-already-built-jar">
+ <echo level="warn" message="Cycle detected: DuskZ was already built"/>
+ </target>
+ <target depends="init,-deps-jar-init" name="deps-jar" unless="no.deps">
+ <mkdir dir="${build.dir}"/>
+ <touch file="${built-jar.properties}" verbose="false"/>
+ <property file="${built-jar.properties}" prefix="already.built.jar."/>
+ <antcall target="-warn-already-built-jar"/>
+ <propertyfile file="${built-jar.properties}">
+ <entry key="${basedir}" value=""/>
+ </propertyfile>
+ <antcall target="-maybe-call-dep">
+ <param name="call.built.properties" value="${built-jar.properties}"/>
+ <param location="${project.DuskCommon}" name="call.subproject"/>
+ <param location="${project.DuskCommon}/build.xml" name="call.script"/>
+ <param name="call.target" value="jar"/>
+ <param name="transfer.built-jar.properties" value="${built-jar.properties}"/>
+ </antcall>
+ </target>
+ <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
+ <target depends="init" name="-check-automatic-build">
+ <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
+ </target>
+ <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
+ <antcall target="clean"/>
+ </target>
+ <target depends="init,deps-jar" name="-pre-pre-compile">
+ <mkdir dir="${build.classes.dir}"/>
+ </target>
+ <target name="-pre-compile">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="do.depend.true" name="-compile-depend">
+ <pathconvert property="build.generated.subdirs">
+ <dirset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </pathconvert>
+ <j2seproject3:depend srcdir="${src.dir}:${build.generated.subdirs}"/>
+ </target>
+ <target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,-compile-depend" if="have.sources" name="-do-compile">
+ <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/>
+ <copy todir="${build.classes.dir}">
+ <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target if="has.persistence.xml" name="-copy-persistence-xml">
+ <mkdir dir="${build.classes.dir}/META-INF"/>
+ <copy todir="${build.classes.dir}/META-INF">
+ <fileset dir="${meta.inf.dir}" includes="persistence.xml orm.xml"/>
+ </copy>
+ </target>
+ <target name="-post-compile">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
+ <target name="-pre-compile-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
+ <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+ <j2seproject3:force-recompile/>
+ <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.dir}"/>
+ </target>
+ <target name="-post-compile-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
+ <!--
+ ====================
+ JAR BUILDING SECTION
+ ====================
+ -->
+ <target depends="init" name="-pre-pre-jar">
+ <dirname file="${dist.jar}" property="dist.jar.dir"/>
+ <mkdir dir="${dist.jar.dir}"/>
+ </target>
+ <target name="-pre-jar">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive" name="-do-jar-without-manifest" unless="manifest.available-mkdist.available">
+ <j2seproject1:jar/>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class-mkdist.available">
+ <j2seproject1:jar manifest="${manifest.file}"/>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
+ <j2seproject1:jar manifest="${manifest.file}">
+ <j2seproject1:manifest>
+ <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
+ </j2seproject1:manifest>
+ </j2seproject1:jar>
+ <echo level="info">To run this application from the command line without Ant, try:</echo>
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <property location="${dist.jar}" name="dist.jar.resolved"/>
+ <pathconvert property="run.classpath.with.dist.jar">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
+ </pathconvert>
+ <echo level="info">${platform.java} -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
+ </target>
+ <target depends="init" if="do.archive" name="-do-jar-with-libraries-create-manifest" unless="manifest.available">
+ <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
+ <touch file="${tmp.manifest.file}" verbose="false"/>
+ </target>
+ <target depends="init" if="do.archive+manifest.available" name="-do-jar-with-libraries-copy-manifest">
+ <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
+ <copy file="${manifest.file}" tofile="${tmp.manifest.file}"/>
+ </target>
+ <target depends="init,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest" if="do.archive+main.class.available" name="-do-jar-with-libraries-set-main">
+ <manifest file="${tmp.manifest.file}" mode="update">
+ <attribute name="Main-Class" value="${main.class}"/>
+ </manifest>
+ </target>
+ <target depends="init,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest" if="do.archive+splashscreen.available" name="-do-jar-with-libraries-set-splashscreen">
+ <basename file="${application.splash}" property="splashscreen.basename"/>
+ <mkdir dir="${build.classes.dir}/META-INF"/>
+ <copy failonerror="false" file="${application.splash}" todir="${build.classes.dir}/META-INF"/>
+ <manifest file="${tmp.manifest.file}" mode="update">
+ <attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/>
+ </manifest>
+ </target>
+ <target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest,-do-jar-with-libraries-set-main,-do-jar-with-libraries-set-splashscreen" if="do.mkdist" name="-do-jar-with-libraries-pack">
+ <j2seproject3:copylibs manifest="${tmp.manifest.file}"/>
+ <echo level="info">To run this application from the command line without Ant, try:</echo>
+ <property location="${dist.jar}" name="dist.jar.resolved"/>
+ <echo level="info">${platform.java} -jar "${dist.jar.resolved}"</echo>
+ </target>
+ <target depends="-do-jar-with-libraries-pack" if="do.archive" name="-do-jar-with-libraries-delete-manifest">
+ <delete>
+ <fileset file="${tmp.manifest.file}"/>
+ </delete>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest,-do-jar-with-libraries-set-main,-do-jar-with-libraries-set-splashscreen,-do-jar-with-libraries-pack,-do-jar-with-libraries-delete-manifest" name="-do-jar-with-libraries"/>
+ <target depends="-jfx-copylibs,-rebase-libs,jfx-deployment" name="-post-jar">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar,-jfx-copylibs,-rebase-libs" description="Build JAR." name="jar"/>
+ <!--
+ =================
+ EXECUTION SECTION
+ =================
+ -->
+ <target depends="init,compile,jar" description="Run a main class." name="run">
+ <j2seproject1:java>
+ <customize>
+ <arg line="${application.args}"/>
+ </customize>
+ </j2seproject1:java>
+ </target>
+ <target name="-do-not-recompile">
+ <property name="javac.includes.binary" value=""/>
+ </target>
+ <target depends="init,compile-single" name="run-single">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <j2seproject1:java classname="${run.class}"/>
+ </target>
+ <target depends="init,compile-test-single" name="run-test-with-main">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/>
+ </target>
+ <!--
+ =================
+ DEBUGGING SECTION
+ =================
+ -->
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger">
+ <j2seproject1:nbjpdastart name="${debug.class}"/>
+ </target>
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger-main-test">
+ <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${debug.class}"/>
+ </target>
+ <target depends="init,compile" name="-debug-start-debuggee">
+ <j2seproject3:debug>
+ <customize>
+ <arg line="${application.args}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee,jar" description="Debug project in IDE." if="netbeans.home" name="debug"/>
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
+ <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
+ </target>
+ <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
+ <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
+ <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+ <j2seproject3:debug classname="${debug.class}"/>
+ </target>
+ <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
+ <target depends="init,compile-test-single" if="netbeans.home" name="-debug-start-debuggee-main-test">
+ <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+ <j2seproject3:debug classname="${debug.class}" classpath="${debug.test.classpath}"/>
+ </target>
+ <target depends="init,compile-test-single,-debug-start-debugger-main-test,-debug-start-debuggee-main-test" if="netbeans.home" name="debug-test-with-main"/>
+ <target depends="init" name="-pre-debug-fix">
+ <fail unless="fix.includes">Must set fix.includes</fail>
+ <property name="javac.includes" value="${fix.includes}.java"/>
+ </target>
+ <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
+ <j2seproject1:nbjpdareload/>
+ </target>
+ <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
+ <!--
+ =================
+ PROFILING SECTION
+ =================
+ -->
+ <!--
+ pre NB7.2 profiler integration
+ -->
+ <target depends="profile-init,compile" description="Profile a project in the IDE." if="profiler.info.jvmargs.agent" name="-profile-pre72">
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <profile/>
+ </target>
+ <target depends="profile-init,compile-single" description="Profile a selected class in the IDE." if="profiler.info.jvmargs.agent" name="-profile-single-pre72">
+ <fail unless="profile.class">Must select one file in the IDE or set profile.class</fail>
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <profile classname="${profile.class}"/>
+ </target>
+ <target depends="profile-init,compile-single" if="profiler.info.jvmargs.agent" name="-profile-applet-pre72">
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <profile classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </profile>
+ </target>
+ <target depends="profile-init,compile-test-single" if="profiler.info.jvmargs.agent" name="-profile-test-single-pre72">
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <junit dir="${profiler.info.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" jvm="${profiler.info.jvm}" showoutput="true">
+ <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
+ <jvmarg value="${profiler.info.jvmargs.agent}"/>
+ <jvmarg line="${profiler.info.jvmargs}"/>
+ <test name="${profile.class}"/>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ </junit>
+ </target>
+ <!--
+ end of pre NB72 profiling section
+ -->
+ <target if="netbeans.home" name="-profile-check">
+ <condition property="profiler.configured">
+ <or>
+ <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-agentpath:"/>
+ <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-javaagent:"/>
+ </or>
+ </condition>
+ </target>
+ <target depends="-profile-check,-profile-pre72,jar" description="Profile a project in the IDE." if="profiler.configured" name="profile" unless="profiler.info.jvmargs.agent">
+ <startprofiler/>
+ <antcall target="run"/>
+ </target>
+ <target depends="-profile-check,-profile-single-pre72" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-single" unless="profiler.info.jvmargs.agent">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <startprofiler/>
+ <antcall target="run-single"/>
+ </target>
+ <target depends="-profile-test-single-pre72" description="Profile a selected test in the IDE." name="profile-test-single"/>
+ <target depends="-profile-check" description="Profile a selected test in the IDE." if="profiler.configured" name="profile-test" unless="profiler.info.jvmargs">
+ <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+ <startprofiler/>
+ <antcall target="test-single"/>
+ </target>
+ <target depends="-profile-check" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-test-with-main">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <startprofiler/>
+ <antcal target="run-test-with-main"/>
+ </target>
+ <target depends="-profile-check,-profile-applet-pre72" if="profiler.configured" name="profile-applet" unless="profiler.info.jvmargs.agent">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <startprofiler/>
+ <antcall target="run-applet"/>
+ </target>
+ <!--
+ ===============
+ JAVADOC SECTION
+ ===============
+ -->
+ <target depends="init" if="have.sources" name="-javadoc-build">
+ <mkdir dir="${dist.javadoc.dir}"/>
+ <condition else="" property="javadoc.endorsed.classpath.cmd.line.arg" value="-J${endorsed.classpath.cmd.line.arg}">
+ <and>
+ <isset property="endorsed.classpath.cmd.line.arg"/>
+ <not>
+ <equals arg1="${endorsed.classpath.cmd.line.arg}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" executable="${platform.javadoc}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
+ <classpath>
+ <path path="${javac.classpath}"/>
+ </classpath>
+ <fileset dir="${src.dir}" excludes="*.java,${excludes}" includes="${includes}">
+ <filename name="**/*.java"/>
+ </fileset>
+ <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="**/*.java"/>
+ <exclude name="*.java"/>
+ </fileset>
+ <arg line="${javadoc.endorsed.classpath.cmd.line.arg}"/>
+ </javadoc>
+ <copy todir="${dist.javadoc.dir}">
+ <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
+ <filename name="**/doc-files/**"/>
+ </fileset>
+ <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="**/doc-files/**"/>
+ </fileset>
+ </copy>
+ </target>
+ <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
+ <nbbrowse file="${dist.javadoc.dir}/index.html"/>
+ </target>
+ <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
+ <!--
+ =========================
+ TEST COMPILATION SECTION
+ =========================
+ -->
+ <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
+ <mkdir dir="${build.test.classes.dir}"/>
+ </target>
+ <target name="-pre-compile-test">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="do.depend.true" name="-compile-test-depend">
+ <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
+ </target>
+ <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
+ <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" processorpath="${javac.test.processorpath}" srcdir="${test.src.dir}"/>
+ <copy todir="${build.test.classes.dir}">
+ <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile-test">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
+ <target name="-pre-compile-test-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
+ <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+ <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
+ <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" processorpath="${javac.test.processorpath}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
+ <copy todir="${build.test.classes.dir}">
+ <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile-test-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
+ <!--
+ =======================
+ TEST EXECUTION SECTION
+ =======================
+ -->
+ <target depends="init" if="have.tests" name="-pre-test-run">
+ <mkdir dir="${build.test.results.dir}"/>
+ </target>
+ <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
+ <j2seproject3:test testincludes="**/*Test.java"/>
+ </target>
+ <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init" if="have.tests" name="test-report"/>
+ <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
+ <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
+ <target depends="init" if="have.tests" name="-pre-test-run-single">
+ <mkdir dir="${build.test.results.dir}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
+ <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+ <j2seproject3:test excludes="" includes="${test.includes}" testincludes="${test.includes}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single-method">
+ <fail unless="test.class">Must select some files in the IDE or set test.class</fail>
+ <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
+ <j2seproject3:test excludes="" includes="${javac.includes}" testincludes="${test.class}" testmethods="${test.method}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method" if="have.tests" name="-post-test-run-single-method">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method,-post-test-run-single-method" description="Run single unit test." name="test-single-method"/>
+ <!--
+ =======================
+ TEST DEBUGGING SECTION
+ =======================
+ -->
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test">
+ <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+ <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testincludes="${javac.includes}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test-method">
+ <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+ <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
+ <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testMethod="${test.method}" testincludes="${test.class}" testmethods="${test.method}"/>
+ </target>
+ <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
+ <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
+ </target>
+ <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
+ <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test-method" name="debug-test-method"/>
+ <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
+ <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
+ </target>
+ <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
+ <!--
+ =========================
+ APPLET EXECUTION SECTION
+ =========================
+ -->
+ <target depends="init,compile-single" name="run-applet">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <j2seproject1:java classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </j2seproject1:java>
+ </target>
+ <!--
+ =========================
+ APPLET DEBUGGING SECTION
+ =========================
+ -->
+ <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <j2seproject3:debug classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
+ <!--
+ ===============
+ CLEANUP SECTION
+ ===============
+ -->
+ <target name="-deps-clean-init" unless="built-clean.properties">
+ <property location="${build.dir}/built-clean.properties" name="built-clean.properties"/>
+ <delete file="${built-clean.properties}" quiet="true"/>
+ </target>
+ <target if="already.built.clean.${basedir}" name="-warn-already-built-clean">
+ <echo level="warn" message="Cycle detected: DuskZ was already built"/>
+ </target>
+ <target depends="init,-deps-clean-init" name="deps-clean" unless="no.deps">
+ <mkdir dir="${build.dir}"/>
+ <touch file="${built-clean.properties}" verbose="false"/>
+ <property file="${built-clean.properties}" prefix="already.built.clean."/>
+ <antcall target="-warn-already-built-clean"/>
+ <propertyfile file="${built-clean.properties}">
+ <entry key="${basedir}" value=""/>
+ </propertyfile>
+ <antcall target="-maybe-call-dep">
+ <param name="call.built.properties" value="${built-clean.properties}"/>
+ <param location="${project.DuskCommon}" name="call.subproject"/>
+ <param location="${project.DuskCommon}/build.xml" name="call.script"/>
+ <param name="call.target" value="clean"/>
+ <param name="transfer.built-clean.properties" value="${built-clean.properties}"/>
+ </antcall>
+ </target>
+ <target depends="init" name="-do-clean">
+ <delete dir="${build.dir}"/>
+ <delete dir="${dist.dir}" followsymlinks="false" includeemptydirs="true"/>
+ </target>
+ <target name="-post-clean">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
+ <target name="-check-call-dep">
+ <property file="${call.built.properties}" prefix="already.built."/>
+ <condition property="should.call.dep">
+ <and>
+ <not>
+ <isset property="already.built.${call.subproject}"/>
+ </not>
+ <available file="${call.script}"/>
+ </and>
+ </condition>
+ </target>
+ <target depends="-check-call-dep" if="should.call.dep" name="-maybe-call-dep">
+ <ant antfile="${call.script}" inheritall="false" target="${call.target}">
+ <propertyset>
+ <propertyref prefix="transfer."/>
+ <mapper from="transfer.*" to="*" type="glob"/>
+ </propertyset>
+ </ant>
+ </target>
+</project>
--- /dev/null
+# Do not modify this property in this configuration. It can be re-generated.
+$label=Run as WebStart
--- /dev/null
+# Do not modify this property in this configuration. It can be re-generated.
+$label=Run in Browser
--- /dev/null
+build.xml.data.CRC32=be5f771c
+build.xml.script.CRC32=d9af4be0
+build.xml.stylesheet.CRC32=28e38971@1.56.1.46
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=46d0094e
+nbproject/build-impl.xml.script.CRC32=21080c51
+nbproject/build-impl.xml.stylesheet.CRC32=c6d2a60f@1.56.1.46
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM TEMPLATE - DO NOT EDIT ***
+*** EDIT ../build.xml INSTEAD ***
+-->
+
+<project name="jfx-impl" default="jfx-deployment" basedir=".." xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1"
+ xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:fx="javafx:com.sun.javafx.tools.ant">
+ <description>JavaFX-specific Ant calls</description>
+
+
+ <!-- Empty placeholders for easier customization in ../build.xml -->
+
+ <target name="-pre-jfx-jar">
+ <!-- Called right before <fx:jar> task. You can override this target in the ../build.xml file. -->
+ </target>
+
+ <target name="-post-jfx-jar">
+ <!-- Called right after <fx:jar> task. You can override this target in the ../build.xml file. -->
+ </target>
+
+ <target name="-pre-jfx-deploy">
+ <!-- Called right before <fx:deploy> task. You can override this target in the ../build.xml file. -->
+ </target>
+
+ <target name="-post-jfx-deploy">
+ <!-- Called right after <fx:deploy> task. You can override this target in the ../build.xml file. -->
+ </target>
+
+ <target name="-pre-jfx-native">
+ <!-- Called right before the call to native packager (just after -pre-jfx-deploy). You can override this target in the ../build.xml file. -->
+ </target>
+
+ <target name="-post-jfx-native">
+ <!-- Called right after the call to native packager (just after -post-jfx-deploy). You can override this target in the ../build.xml file. -->
+ </target>
+
+
+ <!-- Check system and JDK version -->
+
+ <target name="-check-operating-system">
+ <condition property="running.on.mac">
+ <os family="mac"/>
+ </condition>
+ <condition property="running.on.unix">
+ <os family="unix"/>
+ </condition>
+ <condition property="running.on.windows">
+ <os family="windows"/>
+ </condition>
+ <echo message="running.on.mac = ${running.on.mac}" level="verbose"/>
+ <echo message="running.on.unix = ${running.on.unix}" level="verbose"/>
+ <echo message="running.on.windows = ${running.on.windows}" level="verbose"/>
+ </target>
+
+ <target name="-check-platform-home-fxsdk-java" depends="-check-property-javafx.sdk" if="javafx.sdk.defined">
+ <condition property="do.set.platform.home.fxsdk.java">
+ <and>
+ <not><isset property="active.platform.home.java.executable"/></not>
+ <or>
+ <available file="${javafx.sdk}${file.separator}bin${file.separator}java"/>
+ <available file="${javafx.sdk}${file.separator}bin${file.separator}java.exe"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-platform-home-fxsdk-java" depends="-check-platform-home-fxsdk-java" if="do.set.platform.home.fxsdk.java">
+ <property name="active.platform.home.java.executable" value="${javafx.sdk}${file.separator}bin${file.separator}java"/>
+ </target>
+ <target name="-check-platform-home-java" if="platform.home">
+ <condition property="do.set.platform.home.java">
+ <and>
+ <not><isset property="active.platform.home.java.executable"/></not>
+ <or>
+ <available file="${platform.home}${file.separator}bin${file.separator}java"/>
+ <available file="${platform.home}${file.separator}bin${file.separator}java.exe"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-platform-home-java" depends="-set-platform-home-fxsdk-java,-check-platform-home-java" if="do.set.platform.home.java">
+ <property name="active.platform.home.java.executable" value="${platform.home}${file.separator}bin${file.separator}java"/>
+ </target>
+ <target name="-check-platform-home-probjdk-java" unless="active.platform.home.java.executable">
+ <condition property="do.set.platform.home.probjdk.java">
+ <and>
+ <not><isset property="active.platform.home.java.executable"/></not>
+ <or>
+ <available file="${java.home}${file.separator}..${file.separator}bin${file.separator}java"/>
+ <available file="${java.home}${file.separator}..${file.separator}bin${file.separator}java.exe"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-platform-home-probjdk-java" depends="-set-platform-home-java,-check-platform-home-probjdk-java" if="do.set.platform.home.probjdk.java">
+ <property name="active.platform.home.java.executable" value="${java.home}${file.separator}..${file.separator}bin${file.separator}java"/>
+ </target>
+ <target name="-check-platform-home-envjdk-java" unless="active.platform.home.java.executable">
+ <property environment="env"/>
+ <condition property="do.set.platform.home.envjdk.java">
+ <and>
+ <not><isset property="active.platform.home.java.executable"/></not>
+ <or>
+ <available file="${env.JAVA_HOME}${file.separator}bin${file.separator}java"/>
+ <available file="${env.JAVA_HOME}${file.separator}bin${file.separator}java.exe"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-platform-home-envjdk-java" depends="-set-platform-home-probjdk-java,-check-platform-home-envjdk-java" if="do.set.platform.home.envjdk.java">
+ <property environment="env"/>
+ <property name="active.platform.home.java.executable" value="${env.JAVA_HOME}${file.separator}bin${file.separator}java"/>
+ </target>
+ <target name="-check-platform-home-fxrt-java" depends="-check-property-javafx.runtime" if="javafx.runtime.defined">
+ <condition property="do.set.platform.home.fxrt.java">
+ <and>
+ <not><isset property="active.platform.home.java.executable"/></not>
+ <or>
+ <available file="${javafx.runtime}${file.separator}bin${file.separator}java"/>
+ <available file="${javafx.runtime}${file.separator}bin${file.separator}java.exe"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-platform-home-fxrt-java" depends="-set-platform-home-envjdk-java,-check-platform-home-fxrt-java" if="do.set.platform.home.fxrt.java">
+ <property name="active.platform.home.java.executable" value="${javafx.runtime}${file.separator}bin${file.separator}java"/>
+ <echo message="Warning: java executable not found in JDK, evaluating java executable in RT instead." level="info"/>
+ </target>
+ <target name="-check-platform-home-jre-java" unless="active.platform.home.java.executable">
+ <condition property="do.set.platform.home.jre.java">
+ <and>
+ <not><isset property="active.platform.home.java.executable"/></not>
+ <or>
+ <available file="${java.home}${file.separator}bin${file.separator}java"/>
+ <available file="${java.home}${file.separator}bin${file.separator}java.exe"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-platform-home-jre-java" depends="-set-platform-home-fxrt-java,-check-platform-home-jre-java" if="do.set.platform.home.jre.java">
+ <property name="active.platform.home.java.executable" value="${java.home}${file.separator}bin${file.separator}java"/>
+ <echo message="Warning: java executable not found in JDK, evaluating java executable in RT instead." level="info"/>
+ </target>
+ <target name="-check-platform-home" depends="-set-platform-home-jre-java">
+ <echo message="active.platform.home.java.executable = ${active.platform.home.java.executable}" level="verbose"/>
+ <fail message="Error:${line.separator}java executable not found !" unless="active.platform.home.java.executable"/>
+ </target>
+
+ <target name="-check-jdk-version" depends="-do-init,-check-platform-home" unless="jdk-version-checked-in-jfximpl">
+ <local name="version-output"/>
+ <exec executable="${active.platform.home.java.executable}" outputproperty="version-output">
+ <arg value="-version"/>
+ </exec>
+ <echo message="version-output:${line.separator}${version-output}" level="verbose"/>
+ <condition property="have-jdk-older-than-1.6">
+ <or>
+ <contains string="${version-output}" substring="java version "1.0"/>
+ <contains string="${version-output}" substring="java version "1.1"/>
+ <contains string="${version-output}" substring="java version "1.2"/>
+ <contains string="${version-output}" substring="java version "1.3"/>
+ <contains string="${version-output}" substring="java version "1.4"/>
+ <contains string="${version-output}" substring="java version "1.5"/>
+ </or>
+ </condition>
+ <fail message="Error:${line.separator}JavaFX 2.0+ projects require JDK version 1.6+ !" if="have-jdk-older-than-1.6"/>
+ <condition property="have-jdk-7u4or5-mac">
+ <and>
+ <or>
+ <contains string="${version-output}" substring="java version "1.7.0_04"/>
+ <contains string="${version-output}" substring="java version "1.7.0_05"/>
+ </or>
+ <os family="mac"/>
+ </and>
+ </condition>
+ <condition property="have-jdk-pre7u6">
+ <or>
+ <isset property="have-jdk-older-than-1.6"/>
+ <contains string="${version-output}" substring="java version "1.6"/>
+ <contains string="${version-output}" substring="java version "1.7.0""/>
+ <contains string="${version-output}" substring="java version "1.7.0_01"/>
+ <contains string="${version-output}" substring="java version "1.7.0_02"/>
+ <contains string="${version-output}" substring="java version "1.7.0_03"/>
+ <contains string="${version-output}" substring="java version "1.7.0_04"/>
+ <contains string="${version-output}" substring="java version "1.7.0_05"/>
+ </or>
+ </condition>
+ <condition property="have-jdk7-css2bin-bug">
+ <or>
+ <contains string="${version-output}" substring="java version "1.7.0_04"/>
+ <contains string="${version-output}" substring="java version "1.7.0_05"/>
+ <contains string="${version-output}" substring="java version "1.7.0_06"/>
+ <contains string="${version-output}" substring="java version "1.7.0_07"/>
+ <contains string="${version-output}" substring="java version "1.7.0_08"/>
+ <contains string="${version-output}" substring="java version "1.7.0_09"/>
+ <contains string="${version-output}" substring="java version "1.7.0_10"/>
+ <contains string="${version-output}" substring="java version "1.7.0_11"/>
+ </or>
+ </condition>
+ <property name="jdk-version-checked-in-jfximpl" value="true"/>
+ <echo message="have-jdk-7u4or5-mac = ${have-jdk-7u4or5-mac}" level="verbose"/>
+ <echo message="have-jdk-pre7u6 = ${have-jdk-pre7u6}" level="verbose"/>
+ <echo message="have-jdk7-css2bin-bug = ${have-jdk7-css2bin-bug}" level="verbose"/>
+ </target>
+
+ <target name="-check-ant-jre-version" unless="ant-jre-version-checked-in-jfximpl">
+ <local name="version-output"/>
+ <exec executable="${java.home}${file.separator}bin${file.separator}java" outputproperty="version-output">
+ <arg value="-version"/>
+ </exec>
+ <echo message="version-output:${line.separator}${version-output}" level="verbose"/>
+ <condition property="have-ant-jre-pre7u6">
+ <or>
+ <contains string="${version-output}" substring="java version "1.0"/>
+ <contains string="${version-output}" substring="java version "1.1"/>
+ <contains string="${version-output}" substring="java version "1.2"/>
+ <contains string="${version-output}" substring="java version "1.3"/>
+ <contains string="${version-output}" substring="java version "1.4"/>
+ <contains string="${version-output}" substring="java version "1.5"/>
+ <contains string="${version-output}" substring="java version "1.6"/>
+ <contains string="${version-output}" substring="java version "1.7.0""/>
+ <contains string="${version-output}" substring="java version "1.7.0_01"/>
+ <contains string="${version-output}" substring="java version "1.7.0_02"/>
+ <contains string="${version-output}" substring="java version "1.7.0_03"/>
+ <contains string="${version-output}" substring="java version "1.7.0_04"/>
+ <contains string="${version-output}" substring="java version "1.7.0_05"/>
+ </or>
+ </condition>
+ <property name="ant-jre-version-checked-in-jfximpl" value="true"/>
+ <echo message="have-ant-jre-pre7u6 = ${have-ant-jre-pre7u6}" level="verbose"/>
+ </target>
+
+ <target name="-check-jdk-7u4or5-mac" depends="-check-jdk-version" if="have-jdk-7u4or5-mac">
+ <fail message="Error:${line.separator}JDK 7u4 Mac and 7u5 Mac do not support WebStart and JavaFX 2.0+ browser plugin technologies.${line.separator}Please upgrade to JDK 7u6 or later."/>
+ </target>
+
+
+ <!-- Check availability of JavaFX SDK deployment support (ant-javafx.jar) -->
+
+ <target name="-check-endorsed-javafx-ant-classpath">
+ <condition property="endorsed-javafx-ant-classpath-available">
+ <and>
+ <isset property="endorsed.javafx.ant.classpath"/>
+ <not>
+ <equals arg1="${endorsed.javafx.ant.classpath}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <echo message="endorsed-javafx-ant-classpath-available = ${endorsed-javafx-ant-classpath-available}" level="verbose"/>
+ </target>
+
+ <target name="-check-property-javafx.sdk">
+ <echo message="javafx.sdk = ${javafx.sdk}" level="verbose"/>
+ <condition property="javafx.sdk.defined">
+ <and>
+ <isset property="javafx.sdk"/>
+ <not><contains string="${javafx.sdk}" substring="$${platform" casesensitive="false"/></not>
+ </and>
+ </condition>
+ <condition property="javafx.sdk.missing+default">
+ <and>
+ <equals arg1="${platform.active}" arg2="Default_JavaFX_Platform" trim="true"/>
+ <not><isset property="javafx.sdk.defined"/></not>
+ </and>
+ </condition>
+ <condition property="javafx.sdk.missing-default">
+ <and>
+ <not><equals arg1="${platform.active}" arg2="Default_JavaFX_Platform" trim="true"/></not>
+ <not><isset property="javafx.sdk.defined"/></not>
+ </and>
+ </condition>
+ <echo message="javafx.sdk.defined = ${javafx.sdk.defined}" level="verbose"/>
+ <echo message="javafx.sdk.missing+default = ${javafx.sdk.missing+default}" level="verbose"/>
+ <echo message="javafx.sdk.missing-default = ${javafx.sdk.missing-default}" level="verbose"/>
+ </target>
+
+ <target name="-check-ant-javafx-in-fxsdk-lib" depends="-check-property-javafx.sdk" if="javafx.sdk.defined">
+ <condition property="do.set.ant-javafx.in.fxsdk.lib">
+ <and>
+ <not><isset property="ant-javafx.jar.location"/></not>
+ <available file="${javafx.sdk}${file.separator}lib${file.separator}ant-javafx.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-ant-javafx-in-fxsdk-lib" depends="-check-ant-javafx-in-fxsdk-lib" if="do.set.ant-javafx.in.fxsdk.lib">
+ <property name="ant-javafx.jar.location" value="${javafx.sdk}${file.separator}lib${file.separator}ant-javafx.jar"/>
+ </target>
+ <target name="-check-ant-javafx-in-fxsdk-tools" depends="-check-property-javafx.sdk" if="javafx.sdk.defined">
+ <condition property="do.set.ant-javafx.in.fxsdk.tools">
+ <and>
+ <not><isset property="ant-javafx.jar.location"/></not>
+ <available file="${javafx.sdk}${file.separator}tools${file.separator}ant-javafx.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-ant-javafx-in-fxsdk-tools" depends="-set-ant-javafx-in-fxsdk-lib,-check-ant-javafx-in-fxsdk-tools" if="do.set.ant-javafx.in.fxsdk.tools">
+ <property name="ant-javafx.jar.location" value="${javafx.sdk}${file.separator}tools${file.separator}ant-javafx.jar"/>
+ </target>
+ <target name="-check-ant-javafx-in-platform-home-lib" if="platform.home">
+ <condition property="do.set.ant-javafx.in.platform.home.lib">
+ <and>
+ <not><isset property="ant-javafx.jar.location"/></not>
+ <available file="${platform.home}${file.separator}lib${file.separator}ant-javafx.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-ant-javafx-in-platform-home-lib" depends="-set-ant-javafx-in-fxsdk-tools,-check-ant-javafx-in-platform-home-lib" if="do.set.ant-javafx.in.platform.home.lib">
+ <property name="ant-javafx.jar.location" value="${platform.home}${file.separator}lib${file.separator}ant-javafx.jar"/>
+ </target>
+ <target name="-check-ant-javafx-in-platform-home-tools" if="platform.home">
+ <condition property="do.set.ant-javafx.in.platform.home.tools">
+ <and>
+ <not><isset property="ant-javafx.jar.location"/></not>
+ <available file="${platform.home}${file.separator}tools${file.separator}ant-javafx.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-ant-javafx-in-platform-home-tools" depends="-set-ant-javafx-in-platform-home-lib,-check-ant-javafx-in-platform-home-tools" if="do.set.ant-javafx.in.platform.home.tools">
+ <property name="ant-javafx.jar.location" value="${platform.home}${file.separator}tools${file.separator}ant-javafx.jar"/>
+ </target>
+ <target name="-check-ant-javafx-in-probjdk-lib" unless="ant-javafx.jar.location">
+ <condition property="do.set.ant-javafx.in.probjdk.lib">
+ <and>
+ <not><isset property="ant-javafx.jar.location"/></not>
+ <available file="${java.home}${file.separator}..${file.separator}lib${file.separator}ant-javafx.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-ant-javafx-in-probjdk-lib" depends="-set-ant-javafx-in-platform-home-tools,-check-ant-javafx-in-probjdk-lib" if="do.set.ant-javafx.in.probjdk.lib">
+ <property name="ant-javafx.jar.location" value="${java.home}${file.separator}..${file.separator}lib${file.separator}ant-javafx.jar"/>
+ </target>
+ <target name="-check-ant-javafx-in-probjdk-tools" unless="ant-javafx.jar.location">
+ <condition property="do.set.ant-javafx.in.probjdk.tools">
+ <and>
+ <not><isset property="ant-javafx.jar.location"/></not>
+ <available file="${java.home}${file.separator}..${file.separator}tools${file.separator}ant-javafx.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-ant-javafx-in-probjdk-tools" depends="-set-ant-javafx-in-probjdk-lib,-check-ant-javafx-in-probjdk-tools" if="do.set.ant-javafx.in.probjdk.tools">
+ <property name="ant-javafx.jar.location" value="${java.home}${file.separator}..${file.separator}tools${file.separator}ant-javafx.jar"/>
+ </target>
+ <target name="-check-ant-javafx-in-macjdk-lib" unless="ant-javafx.jar.location">
+ <condition property="do.set.ant-javafx.in.macjdk.lib">
+ <and>
+ <not><isset property="ant-javafx.jar.location"/></not>
+ <available file="${java.home}${file.separator}lib${file.separator}ant-javafx.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-ant-javafx-in-macjdk-lib" depends="-set-ant-javafx-in-probjdk-tools,-check-ant-javafx-in-macjdk-lib" if="do.set.ant-javafx.in.macjdk.lib">
+ <property name="ant-javafx.jar.location" value="${java.home}${file.separator}lib${file.separator}ant-javafx.jar"/>
+ </target>
+ <target name="-check-ant-javafx-in-envjdk-lib" unless="ant-javafx.jar.location">
+ <property environment="env"/>
+ <condition property="do.set.ant-javafx.in.envjdk.lib">
+ <and>
+ <not><isset property="ant-javafx.jar.location"/></not>
+ <available file="${env.JAVA_HOME}${file.separator}lib${file.separator}ant-javafx.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-ant-javafx-in-envjdk-lib" depends="-set-ant-javafx-in-macjdk-lib,-check-ant-javafx-in-envjdk-lib" if="do.set.ant-javafx.in.envjdk.lib">
+ <property name="ant-javafx.jar.location" value="${env.JAVA_HOME}${file.separator}lib${file.separator}ant-javafx.jar"/>
+ </target>
+ <target name="-check-ant-javafx-in-envjdk-tools" unless="ant-javafx.jar.location">
+ <property environment="env"/>
+ <condition property="do.set.ant-javafx.in.envjdk.tools">
+ <and>
+ <not><isset property="ant-javafx.jar.location"/></not>
+ <available file="${env.JAVA_HOME}${file.separator}tools${file.separator}ant-javafx.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-ant-javafx-in-envjdk-tools" depends="-set-ant-javafx-in-envjdk-lib,-check-ant-javafx-in-envjdk-tools" if="do.set.ant-javafx.in.envjdk.tools">
+ <property name="ant-javafx.jar.location" value="${env.JAVA_HOME}${file.separator}tools${file.separator}ant-javafx.jar"/>
+ </target>
+ <target name="-pre-check-ant-javafx-version" depends="-set-ant-javafx-in-envjdk-tools" unless="ant-javafx-version-already-checked-in-jfximpl">
+ <condition property="do.check.ant-javafx.version">
+ <and>
+ <isset property="ant-javafx.jar.location"/>
+ <not><isset property="ant-javafx-version-already-checked-in-jfximpl"/></not>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-endorsed-javafx-ant-classpath" depends="-check-endorsed-javafx-ant-classpath,-pre-check-ant-javafx-version" if="endorsed-javafx-ant-classpath-available">
+ <property name="javafx.ant.classpath" value="${endorsed.javafx.ant.classpath}:${ant-javafx.jar.location}"/>
+ </target>
+ <target name="-set-javafx-ant-classpath" depends="-check-endorsed-javafx-ant-classpath,-pre-check-ant-javafx-version" unless="endorsed-javafx-ant-classpath-available">
+ <property name="javafx.ant.classpath" value="${ant-javafx.jar.location}"/>
+ </target>
+ <target name="-check-ant-javafx-version" depends="-pre-check-ant-javafx-version,
+ -set-endorsed-javafx-ant-classpath,-set-javafx-ant-classpath" if="do.check.ant-javafx.version">
+ <echo message="ant-javafx.jar.location = ${ant-javafx.jar.location}" level="verbose"/>
+ <echo message="javafx.ant.classpath = ${javafx.ant.classpath}" level="verbose"/>
+ <taskdef resource="com/sun/javafx/tools/ant/antlib.xml"
+ uri="javafx:com.sun.javafx.tools.ant"
+ classpath="${javafx.ant.classpath}"/>
+ <condition property="have-fx-ant-init">
+ <typefound name="javafx:com.sun.javafx.tools.ant:init-ant"/>
+ </condition>
+ <property name="ant-javafx-version-already-checked-in-jfximpl" value="true"/>
+ <echo message="have-fx-ant-init = ${have-fx-ant-init}" level="verbose"/>
+ </target>
+ <target name="-check-jfx-sdk-version-old" depends="-check-ant-javafx-version" unless="have-fx-ant-init">
+ <property name="javafx.ant.version" value="1.0"/>
+ </target>
+ <target name="-check-jfx-sdk-version-new" depends="-check-ant-javafx-version" if="have-fx-ant-init">
+ <fx:init-ant/>
+ <condition property="have-fx-ant-api-1.1">
+ <!-- new features from JavaFX 2.0.2 are available in API version 1.1 or later -->
+ <matches pattern="1.[1-9]" string="${javafx.ant.version}"/>
+ </condition>
+ <condition property="have-fx-ant-api-1.2">
+ <!-- new features from JavaFX 2.2 are available in API version 1.2 or later -->
+ <matches pattern="1.[2-9]" string="${javafx.ant.version}"/>
+ </condition>
+ </target>
+ <target name="-check-jfx-sdk-version" depends="-check-jfx-sdk-version-old, -check-jfx-sdk-version-new" unless="jfx.sdk.version.checked">
+ <echo message="Detected JavaFX Ant API version ${javafx.ant.version}" level="info"/>
+ <echo message="have-fx-ant-api-1.1 = ${have-fx-ant-api-1.1}" level="verbose"/>
+ <echo message="have-fx-ant-api-1.2 = ${have-fx-ant-api-1.2}" level="verbose"/>
+ <echo message="javafx.ant.classpath = ${javafx.ant.classpath}" level="verbose"/>
+ <property name="jfx.sdk.version.checked" value="true"/>
+ </target>
+
+ <target name="-check-jfx-deployment" depends="-check-jdk-version,-check-jfx-sdk-version">
+ <condition property="jfx-deployment-available">
+ <and>
+ <or>
+ <isset property="do.set.ant-javafx.in.fxsdk.lib"/>
+ <isset property="do.set.ant-javafx.in.fxsdk.tools"/>
+ <isset property="do.set.ant-javafx.in.platform.home.lib"/>
+ <isset property="do.set.ant-javafx.in.platform.home.tools"/>
+ <isset property="do.set.ant-javafx.in.probjdk.lib"/>
+ <isset property="do.set.ant-javafx.in.probjdk.tools"/>
+ <isset property="do.set.ant-javafx.in.envjdk.lib"/>
+ <isset property="do.set.ant-javafx.in.envjdk.tools"/>
+ </or>
+ <isset property="ant-javafx.jar.location"/>
+ </and>
+ </condition>
+ <condition property="jfx-deployment-missing+jdk7u6">
+ <and>
+ <not><isset property="jfx-deployment-available"/></not>
+ <not><isset property="have-jdk-pre7u6"/></not>
+ </and>
+ </condition>
+ <condition property="jfx-deployment-missing+javafx.sdk.missing+default">
+ <and>
+ <not><isset property="jfx-deployment-available"/></not>
+ <isset property="have-jdk-pre7u6"/>
+ <isset property="javafx.sdk.missing+default"/>
+ </and>
+ </condition>
+ <condition property="jfx-deployment-missing+javafx.sdk.missing-default">
+ <and>
+ <not><isset property="jfx-deployment-available"/></not>
+ <isset property="have-jdk-pre7u6"/>
+ <isset property="javafx.sdk.missing-default"/>
+ </and>
+ </condition>
+ <fail message="Error:${line.separator}JavaFX deployment library not found in active JDK.${line.separator}Please check that the JDK is correctly installed and its version is at least 7u4 on Mac or 7u6 on other systems." if="jfx-deployment-missing+jdk7u6"/>
+ <fail message="Error:${line.separator}JavaFX deployment library not found.${line.separator}JavaFX SDK path undefined. Check the definition of ${platform.active} in Java Platform Manager${line.separator}(or directly the properties platform.active and javafx.sdk in project.properties file).${line.separator}Note: If missing, the default JavaFX-enabled platform gets created automatically when creating a new JavaFX Project." if="jfx-deployment-missing+javafx.sdk.missing+default"/>
+ <fail message="Error:${line.separator}JavaFX deployment library not found.${line.separator}JavaFX SDK path undefined. Check the definition of ${platform.active} in Java Platform Manager${line.separator}(or directly the properties platform.active and javafx.sdk in project.properties file)." if="jfx-deployment-missing+javafx.sdk.missing-default"/>
+ <fail message="Error:${line.separator}JavaFX deployment library not found." unless="jfx-deployment-available"/>
+ <echo message="jfx-deployment-available = ${jfx-deployment-available}" level="verbose"/>
+ </target>
+
+
+ <!-- Check availability of main JavaFX runtime jar (jfxrt.jar) -->
+
+ <target name="-check-property-javafx.runtime">
+ <echo message="javafx.runtime = ${javafx.runtime}" level="verbose"/>
+ <condition property="javafx.runtime.defined">
+ <and>
+ <isset property="javafx.runtime"/>
+ <not><contains string="${javafx.runtime}" substring="$${platform" casesensitive="false"/></not>
+ </and>
+ </condition>
+ <condition property="javafx.runtime.missing+default">
+ <and>
+ <equals arg1="${platform.active}" arg2="Default_JavaFX_Platform" trim="true"/>
+ <not><isset property="javafx.runtime.defined"/></not>
+ </and>
+ </condition>
+ <condition property="javafx.runtime.missing-default">
+ <and>
+ <not><equals arg1="${platform.active}" arg2="Default_JavaFX_Platform" trim="true"/></not>
+ <not><isset property="javafx.runtime.defined"/></not>
+ </and>
+ </condition>
+ <echo message="javafx.runtime.defined = ${javafx.runtime.defined}" level="verbose"/>
+ <echo message="javafx.runtime.missing+default = ${javafx.runtime.missing+default}" level="verbose"/>
+ <echo message="javafx.runtime.missing-default = ${javafx.runtime.missing-default}" level="verbose"/>
+ </target>
+
+ <target name="-check-jfxrt-in-fxrt" depends="-check-property-javafx.runtime" if="javafx.runtime.defined">
+ <condition property="do.set.jfxrt.in.fxrt">
+ <and>
+ <not><isset property="jfxrt.jar.location"/></not>
+ <available file="${javafx.runtime}${file.separator}lib${file.separator}jfxrt.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-jfxrt-in-fxrt" depends="-check-jfxrt-in-fxrt" if="do.set.jfxrt.in.fxrt">
+ <property name="jfxrt.jar.location" value="${javafx.runtime}${file.separator}lib${file.separator}jfxrt.jar"/>
+ </target>
+ <target name="-check-jfxrt-in-fxsdk-jre" depends="-check-property-javafx.sdk" if="javafx.sdk.defined">
+ <condition property="do.set.jfxrt.in.fxsdk.jre">
+ <and>
+ <not><isset property="jfxrt.jar.location"/></not>
+ <available file="${javafx.sdk}${file.separator}jre${file.separator}lib${file.separator}jfxrt.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-jfxrt-in-fxsdk-jre" depends="-set-jfxrt-in-fxrt,-check-jfxrt-in-fxsdk-jre" if="do.set.jfxrt.in.fxsdk.jre">
+ <property name="jfxrt.jar.location" value="${javafx.sdk}${file.separator}jre${file.separator}lib${file.separator}jfxrt.jar"/>
+ </target>
+ <target name="-check-jfxrt-in-fxsdk-rt" depends="-check-property-javafx.sdk" if="javafx.sdk.defined">
+ <condition property="do.set.jfxrt.in.fxsdk.rt">
+ <and>
+ <not><isset property="jfxrt.jar.location"/></not>
+ <available file="${javafx.sdk}${file.separator}rt${file.separator}lib${file.separator}jfxrt.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-jfxrt-in-fxsdk-rt" depends="-set-jfxrt-in-fxsdk-jre,-check-jfxrt-in-fxsdk-rt" if="do.set.jfxrt.in.fxsdk.rt">
+ <property name="jfxrt.jar.location" value="${javafx.sdk}${file.separator}rt${file.separator}lib${file.separator}jfxrt.jar"/>
+ </target>
+ <target name="-check-jfxrt-in-platform-home-jre" if="platform.home">
+ <condition property="do.set.jfxrt.in.platform.home.jre">
+ <and>
+ <not><isset property="jfxrt.jar.location"/></not>
+ <available file="${platform.home}${file.separator}jre${file.separator}lib${file.separator}jfxrt.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-jfxrt-in-platform-home-jre" depends="-set-jfxrt-in-fxsdk-rt,-check-jfxrt-in-platform-home-jre" if="do.set.jfxrt.in.platform.home.jre">
+ <property name="jfxrt.jar.location" value="${platform.home}${file.separator}jre${file.separator}lib${file.separator}jfxrt.jar"/>
+ </target>
+ <target name="-check-jfxrt-in-platform-home-rt" if="platform.home">
+ <condition property="do.set.jfxrt.in.platform.home.rt">
+ <and>
+ <not><isset property="jfxrt.jar.location"/></not>
+ <available file="${platform.home}${file.separator}rt${file.separator}lib${file.separator}jfxrt.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-jfxrt-in-platform-home-rt" depends="-set-jfxrt-in-platform-home-jre,-check-jfxrt-in-platform-home-rt" if="do.set.jfxrt.in.platform.home.rt">
+ <property name="jfxrt.jar.location" value="${platform.home}${file.separator}rt${file.separator}lib${file.separator}jfxrt.jar"/>
+ </target>
+ <target name="-check-jfxrt-in-jre" unless="jfxrt.jar.location">
+ <condition property="do.set.jfxrt.in.jre">
+ <and>
+ <not><isset property="jfxrt.jar.location"/></not>
+ <available file="${java.home}${file.separator}lib${file.separator}jfxrt.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-jfxrt-in-jre" depends="-set-jfxrt-in-platform-home-rt,-check-jfxrt-in-jre" if="do.set.jfxrt.in.jre">
+ <property name="jfxrt.jar.location" value="${java.home}${file.separator}lib${file.separator}jfxrt.jar"/>
+ </target>
+ <target name="-check-jfxrt-in-envjdk-jre" unless="jfxrt.jar.location">
+ <property environment="env"/>
+ <condition property="do.set.jfxrt.in.envjdk.jre">
+ <and>
+ <not><isset property="ant-javafx.jar.location"/></not>
+ <available file="${env.JAVA_HOME}${file.separator}jre${file.separator}lib${file.separator}jfxrt.jar"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-jfxrt-in-envjdk-jre" depends="-set-jfxrt-in-jre,-check-jfxrt-in-envjdk-jre" if="do.set.jfxrt.in.envjdk.jre">
+ <property name="jfxrt.jar.location" value="${env.JAVA_HOME}${file.separator}jre${file.separator}lib${file.separator}jfxrt.jar"/>
+ </target>
+ <target name="-pre-check-jfx-runtime" depends="-set-jfxrt-in-envjdk-jre">
+ <echo message="jfxrt.jar.location = ${jfxrt.jar.location}" level="verbose"/>
+ </target>
+
+ <target name="-check-jfx-runtime" depends="-check-jdk-version, -pre-check-jfx-runtime">
+ <condition property="jfx-runtime-available">
+ <and>
+ <or>
+ <isset property="do.set.jfxrt.in.fxrt"/>
+ <isset property="do.set.jfxrt.in.fxsdk.jre"/>
+ <isset property="do.set.jfxrt.in.fxsdk.rt"/>
+ <isset property="do.set.jfxrt.in.platform.home.jre"/>
+ <isset property="do.set.jfxrt.in.platform.home.rt"/>
+ <isset property="do.set.jfxrt.in.jre"/>
+ <isset property="do.set.jfxrt.in.envjdk.jre"/>
+ </or>
+ <isset property="jfxrt.jar.location"/>
+ </and>
+ </condition>
+ <fail message="Error:${line.separator}JavaFX runtime JAR not found." unless="jfx-runtime-available"/>
+ <echo message="jfx-runtime-available = ${jfx-runtime-available}" level="verbose"/>
+ </target>
+
+
+ <!-- Check availability of WebStart executable -->
+
+ <target name="-check-webstart-in-fxrt" depends="-check-property-javafx.runtime" if="javafx.runtime.defined">
+ <condition property="do.set.webstart.in.fxrt">
+ <and>
+ <not><isset property="active.webstart.executable"/></not>
+ <isset property="javafx.runtime.defined"/>
+ <or>
+ <available file="${javafx.runtime}${file.separator}bin${file.separator}javaws.exe"/>
+ <available file="${javafx.runtime}${file.separator}bin${file.separator}javaws"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-webstart-in-fxrt" depends="-check-webstart-in-fxrt" if="do.set.webstart.in.fxrt">
+ <property name="active.webstart.executable" value="${javafx.runtime}${file.separator}bin${file.separator}javaws"/>
+ </target>
+ <target name="-check-webstart-in-fxsdk-jre" depends="-check-property-javafx.sdk" if="javafx.sdk.defined">
+ <condition property="do.set.webstart.in.fxsdk.jre">
+ <and>
+ <not><isset property="active.webstart.executable"/></not>
+ <isset property="javafx.sdk.defined"/>
+ <or>
+ <available file="${javafx.sdk}${file.separator}jre${file.separator}bin${file.separator}javaws.exe"/>
+ <available file="${javafx.sdk}${file.separator}jre${file.separator}bin${file.separator}javaws"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-webstart-in-fxsdk-jre" depends="-set-webstart-in-fxrt,-check-webstart-in-fxsdk-jre" if="do.set.webstart.in.fxsdk.jre">
+ <property name="active.webstart.executable" value="${javafx.sdk}${file.separator}jre${file.separator}bin${file.separator}javaws"/>
+ </target>
+ <target name="-check-webstart-in-fxsdk" depends="-check-property-javafx.sdk" if="javafx.sdk.defined">
+ <condition property="do.set.webstart.in.fxsdk">
+ <and>
+ <not><isset property="active.webstart.executable"/></not>
+ <isset property="javafx.sdk.defined"/>
+ <or>
+ <available file="${javafx.sdk}${file.separator}bin${file.separator}javaws.exe"/>
+ <available file="${javafx.sdk}${file.separator}bin${file.separator}javaws"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-webstart-in-fxsdk" depends="-set-webstart-in-fxsdk-jre,-check-webstart-in-fxsdk" if="do.set.webstart.in.fxsdk">
+ <property name="active.webstart.executable" value="${javafx.sdk}${file.separator}bin${file.separator}javaws"/>
+ </target>
+ <target name="-check-webstart-in-platform-home-jre" if="platform.home">
+ <condition property="do.set.webstart.in.platform.home.jre">
+ <and>
+ <not><isset property="active.webstart.executable"/></not>
+ <or>
+ <available file="${platform.home}${file.separator}jre${file.separator}bin${file.separator}javaws.exe"/>
+ <available file="${platform.home}${file.separator}jre${file.separator}bin${file.separator}javaws"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-webstart-in-platform-home-jre" depends="-set-webstart-in-fxsdk,-check-webstart-in-platform-home-jre" if="do.set.webstart.in.platform.home.jre">
+ <property name="active.webstart.executable" value="${platform.home}${file.separator}jre${file.separator}bin${file.separator}javaws"/>
+ </target>
+ <target name="-check-webstart-in-platform-home" if="platform.home">
+ <condition property="do.set.webstart.in.platform.home">
+ <and>
+ <not><isset property="active.webstart.executable"/></not>
+ <or>
+ <available file="${platform.home}${file.separator}bin${file.separator}javaws.exe"/>
+ <available file="${platform.home}${file.separator}bin${file.separator}javaws"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-webstart-in-platform-home" depends="-set-webstart-in-platform-home-jre,-check-webstart-in-platform-home" if="do.set.webstart.in.platform.home">
+ <property name="active.webstart.executable" value="${platform.home}${file.separator}bin${file.separator}javaws"/>
+ </target>
+ <target name="-check-webstart-in-jre" unless="active.webstart.executable">
+ <condition property="do.set.webstart.in.jre">
+ <and>
+ <not><isset property="active.webstart.executable"/></not>
+ <or>
+ <available file="${java.home}${file.separator}bin${file.separator}javaws.exe"/>
+ <available file="${java.home}${file.separator}bin${file.separator}javaws"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-webstart-in-jre" depends="-set-webstart-in-platform-home,-check-webstart-in-jre" if="do.set.webstart.in.jre">
+ <property name="active.webstart.executable" value="${java.home}${file.separator}bin${file.separator}javaws"/>
+ </target>
+ <target name="-check-webstart-in-probjdk" unless="active.webstart.executable">
+ <condition property="do.set.webstart.in.probjdk">
+ <and>
+ <not><isset property="active.webstart.executable"/></not>
+ <or>
+ <available file="${java.home}${file.separator}..${file.separator}bin${file.separator}javaws.exe"/>
+ <available file="${java.home}${file.separator}..${file.separator}bin${file.separator}javaws"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-webstart-in-probjdk" depends="-set-webstart-in-jre,-check-webstart-in-probjdk" if="do.set.webstart.in.probjdk">
+ <property name="active.webstart.executable" value="${java.home}${file.separator}..${file.separator}bin${file.separator}javaws"/>
+ </target>
+ <target name="-check-webstart-in-envjdk" unless="active.webstart.executable">
+ <property environment="env"/>
+ <condition property="do.set.webstart.in.envjdk">
+ <and>
+ <not><isset property="active.webstart.executable"/></not>
+ <or>
+ <available file="${env.JAVA_HOME}${file.separator}bin${file.separator}javaws.exe"/>
+ <available file="${env.JAVA_HOME}${file.separator}bin${file.separator}javaws"/>
+ </or>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-webstart-in-envjdk" depends="-set-webstart-in-probjdk,-check-webstart-in-envjdk" if="do.set.webstart.in.envjdk">
+ <property name="active.webstart.executable" value="${env.JAVA_HOME}${file.separator}bin${file.separator}javaws"/>
+ </target>
+ <target name="-pre-check-webstart-in-unix" depends="-check-operating-system,-set-webstart-in-envjdk" unless="active.webstart.executable">
+ <condition property="running.on.unix-active.webstart.executable">
+ <and>
+ <not><isset property="active.webstart.executable"/></not>
+ <isset property="running.on.unix"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-check-webstart-in-unix" depends="-pre-check-webstart-in-unix" if="running.on.unix-active.webstart.executable">
+ <local name="exec.which.javaws.result"/>
+ <exec executable="which" failifexecutionfails="false" failonerror="false" resultproperty="exec.which.javaws.result" outputproperty="exec.which.javaws.output">
+ <arg value="javaws"/>
+ </exec>
+ <condition property="do.set.webstart.in.unix">
+ <and>
+ <not><isset property="active.webstart.executable"/></not>
+ <isset property="exec.which.javaws.result"/>
+ <equals arg1="${exec.which.javaws.result}" arg2="0"/>
+ <isset property="exec.which.javaws.output"/>
+ <not><equals arg1="${exec.which.javaws.output}" arg2=""/></not>
+ </and>
+ </condition>
+ <echo message="do.set.webstart.in.unix = ${do.set.webstart.in.unix}" level="verbose"/>
+ </target>
+ <target name="-set-webstart-in-unix" depends="-set-webstart-in-envjdk,-check-webstart-in-unix" if="do.set.webstart.in.unix">
+ <property name="active.webstart.executable" value="${exec.which.javaws.output}"/>
+ </target>
+ <target name="-pre-check-jfx-webstart" depends="-set-webstart-in-unix">
+ <echo message="active.webstart.executable = ${active.webstart.executable}" level="verbose"/>
+ </target>
+
+ <target name="-check-jfx-webstart" depends="-pre-check-jfx-webstart">
+ <condition property="jfx-webstart-available">
+ <and>
+ <or>
+ <isset property="do.set.webstart.in.fxrt"/>
+ <isset property="do.set.webstart.in.fxsdk.jre"/>
+ <isset property="do.set.webstart.in.fxsdk"/>
+ <isset property="do.set.webstart.in.platform.home.jre"/>
+ <isset property="do.set.webstart.in.platform.home"/>
+ <isset property="do.set.webstart.in.jre"/>
+ <isset property="do.set.webstart.in.probjdk"/>
+ <isset property="do.set.webstart.in.envjdk"/>
+ <isset property="do.set.webstart.in.unix"/>
+ </or>
+ <isset property="active.webstart.executable"/>
+ </and>
+ </condition>
+ <condition property="jfx-webstart-missing+jdk7u6">
+ <and>
+ <not><isset property="jfx-webstart-available"/></not>
+ <not><isset property="have-jdk-pre7u6"/></not>
+ </and>
+ </condition>
+ <condition property="jfx-webstart-missing+javafx.runtime.missing+default">
+ <and>
+ <not><isset property="jfx-webstart-available"/></not>
+ <isset property="have-jdk-pre7u6"/>
+ <isset property="javafx.runtime.missing+default"/>
+ </and>
+ </condition>
+ <condition property="jfx-webstart-missing+javafx.runtime.missing-default">
+ <and>
+ <not><isset property="jfx-webstart-available"/></not>
+ <isset property="have-jdk-pre7u6"/>
+ <isset property="javafx.runtime.missing-default"/>
+ </and>
+ </condition>
+ <fail message="Error:${line.separator}WebStart executable could not be found in active JDK.${line.separator}Please check that the JDK is correctly installed and its version is at least 7u6." if="jfx-webstart-missing+jdk7u6"/>
+ <fail message="Error:${line.separator}WebStart executable could not be found.${line.separator}JavaFX RT path undefined. Check the definition of ${platform.active} in Java Platform Manager${line.separator}(or directly the properties platform.active and javafx.runtime in project.properties file).${line.separator}Note: If missing, the default JavaFX-enabled platform gets created automatically when creating a new JavaFX Project." if="jfx-webstart-missing+javafx.runtime.missing+default"/>
+ <fail message="Error:${line.separator}WebStart executable could not be found.${line.separator}JavaFX RT path undefined. Check the definition of ${platform.active} in Java Platform Manager${line.separator}(or directly the properties platform.active and javafx.runtime in project.properties file)." if="jfx-webstart-missing+javafx.runtime.missing-default"/>
+ <fail message="Error:${line.separator}WebStart executable could not be found." unless="jfx-webstart-available"/>
+ <echo message="jfx-webstart-available = ${jfx-webstart-available}" level="verbose"/>
+ </target>
+
+
+ <!-- Legacy targets kept for compatibility with older build-impl.xml scripts -->
+
+ <!-- Note: target "-check-javafx" is not necessary any more but is referenced from NB 7.1 build-impl.xml -->
+ <target name="-check-javafx"/>
+ <!-- Note: target "-javafx-check-error" is not necessary any more but is referenced from NB 7.1 build-impl.xml -->
+ <target name="-javafx-check-error"/>
+ <!-- Note: target "-init-javafx" is not necessary any more but is referenced from NB 7.1 build-impl.xml -->
+ <target name="-init-javafx"/>
+
+
+ <!-- Check project properties -->
+
+ <target name="-check-default-run-config" unless="config">
+ <property name="config" value="<default config>"/>
+ </target>
+
+ <target name="-check-project">
+ <condition property="main-class-available">
+ <isset property="javafx.main.class"/>
+ </condition>
+ <condition property="vmargs-available">
+ <and>
+ <isset property="run.jvmargs"/>
+ <not><equals arg1="${run.jvmargs}" arg2=""/></not>
+ </and>
+ </condition>
+ <condition property="preloader-available">
+ <and>
+ <isset property="javafx.preloader.enabled"/>
+ <equals arg1="${javafx.preloader.enabled}" arg2="true"/>
+ <isset property="javafx.preloader.class"/>
+ <not><equals arg1="${javafx.preloader.class}" arg2=""/></not>
+ <isset property="javafx.preloader.jar.filename"/>
+ <not><equals arg1="${javafx.preloader.jar.filename}" arg2=""/></not>
+ </and>
+ </condition>
+ <condition property="app-with-preloader">
+ <and>
+ <istrue value="${preloader-available}"/>
+ <istrue value="${main-class-available}"/>
+ </and>
+ </condition>
+ <condition property="app-with-external-preloader-jar">
+ <and>
+ <isset property="app-with-preloader"/>
+ <isset property="javafx.preloader.type"/>
+ <equals arg1="${javafx.preloader.type}" arg2="jar" trim="true"/>
+ </and>
+ </condition>
+ <condition property="app-without-preloader">
+ <and>
+ <not>
+ <istrue value="${preloader-available}"/>
+ </not>
+ <istrue value="${main-class-available}"/>
+ </and>
+ </condition>
+ <condition property="preloader-app">
+ <and>
+ <isset property="javafx.preloader"/>
+ <equals arg1="${javafx.preloader}" arg2="true"/>
+ </and>
+ </condition>
+ <condition property="fx-in-swing-app">
+ <and>
+ <isset property="javafx.swing"/>
+ <equals arg1="${javafx.swing}" arg2="true"/>
+ </and>
+ </condition>
+ <condition property="fx-in-swing-workaround-app">
+ <and>
+ <istrue value="${fx-in-swing-app}"/>
+ <istrue value="${preloader-app}"/>
+ </and>
+ </condition>
+ <condition property="preloader-app-no-workaround">
+ <and>
+ <istrue value="${preloader-app}"/>
+ <not><istrue value="${fx-in-swing-app}"/></not>
+ </and>
+ </condition>
+ <condition property="html-template-available">
+ <and>
+ <isset property="javafx.run.htmltemplate"/>
+ <not>
+ <equals arg1="${javafx.run.htmltemplate}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <condition property="icon-available">
+ <and>
+ <isset property="javafx.deploy.icon"/>
+ <not>
+ <equals arg1="${javafx.deploy.icon}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <condition property="dimensions-available">
+ <and>
+ <isset property="javafx.run.width"/>
+ <isset property="javafx.run.height"/>
+ <not><equals arg1="${javafx.run.width}" arg2=""/></not>
+ <not><equals arg1="${javafx.run.height}" arg2=""/></not>
+ </and>
+ </condition>
+ <condition property="update-mode-background">
+ <and>
+ <isset property="javafx.deploy.backgroundupdate"/>
+ <equals arg1="${javafx.deploy.backgroundupdate}" arg2="true" trim="true"/>
+ </and>
+ </condition>
+ <condition property="offline-allowed">
+ <and>
+ <isset property="javafx.deploy.allowoffline"/>
+ <equals arg1="${javafx.deploy.allowoffline}" arg2="true" trim="true"/>
+ </and>
+ </condition>
+ <condition property="permissions-elevated">
+ <and>
+ <isset property="javafx.deploy.permissionselevated"/>
+ <equals arg1="${javafx.deploy.permissionselevated}" arg2="true" trim="true"/>
+ </and>
+ </condition>
+ <condition property="binary-encode-css">
+ <and>
+ <isset property="javafx.binarycss"/>
+ <equals arg1="${javafx.binarycss}" arg2="true" trim="true"/>
+ </and>
+ </condition>
+ <condition property="rebase-lib-jars">
+ <and>
+ <isset property="javafx.rebase.libs"/>
+ <equals arg1="${javafx.rebase.libs}" arg2="true" trim="true"/>
+ </and>
+ </condition>
+ <echo message="main-class-available = ${main-class-available}" level="verbose"/>
+ <echo message="vmargs-available = ${vmargs-available}" level="verbose"/>
+ <echo message="preloader-available = ${preloader-available}" level="verbose"/>
+ <echo message="app-with-preloader = ${app-with-preloader}" level="verbose"/>
+ <echo message="app-with-preloader-without-project = ${app-with-preloader-without-project}" level="verbose"/>
+ <echo message="app-without-preloader = ${app-without-preloader}" level="verbose"/>
+ <echo message="preloader-app = ${preloader-app}" level="verbose"/>
+ <echo message="fx-in-swing-app = ${fx-in-swing-app}" level="verbose"/>
+ <echo message="fx-in-swing-workaround-app = ${fx-in-swing-workaround-app}" level="verbose"/>
+ <echo message="preloader-app-no-workaround = ${preloader-app-no-workaround}" level="verbose"/>
+ <echo message="html-template-available = ${html-template-available}" level="verbose"/>
+ <echo message="icon-available = ${icon-available}" level="verbose"/>
+ <echo message="dimensions-available = ${dimensions-available}" level="verbose"/>
+ <echo message="update-mode-background = ${update-mode-background}" level="verbose"/>
+ <echo message="offline-allowed = ${offline-allowed}" level="verbose"/>
+ <echo message="permissions-elevated = ${permissions-elevated}" level="verbose"/>
+ <echo message="binary-encode-css = ${binary-encode-css}" level="verbose"/>
+ <echo message="rebase-lib-jars = ${rebase-lib-jars}" level="verbose"/>
+ </target>
+
+ <target name="-swing-api-check" depends="-check-project,-check-jfx-deployment" if="fx-in-swing-app">
+ <condition property="fx-in-swing-app-workaround">
+ <and>
+ <isset property="fx-in-swing-app"/>
+ <not><isset property="have-fx-ant-api-1.2"/></not>
+ </and>
+ </condition>
+ </target>
+ <target name="-swing-api-warning" depends="-swing-api-check" if="fx-in-swing-app-workaround">
+ <echo message="Info: No support for FX-in-Swing deployment detected in current JavaFX SDK. Using workaround instead."/>
+ </target>
+
+ <target name="-icon-deployment-check" depends="-check-project,-check-jfx-deployment" if="icon-available">
+ <condition property="icon-deployment-may-not-be-supported">
+ <and>
+ <isset property="icon-available"/>
+ <not><isset property="have-fx-ant-api-1.1"/></not>
+ </and>
+ </condition>
+ </target>
+ <target name="-icon-warning" depends="-icon-deployment-check" if="icon-deployment-may-not-be-supported">
+ <echo message="Warning: Note that due to a bug in early JavaFX 2.0 SDK distributions the icon may not be properly set in deployment files."/>
+ </target>
+
+ <target name="-set-dimensions" depends="-check-project" if="dimensions-available">
+ <property name="javafx.width" value="${javafx.run.width}"/>
+ <property name="javafx.height" value="${javafx.run.height}"/>
+ </target>
+ <target name="-reset-dimensions" depends="-check-project" unless="dimensions-available">
+ <property name="javafx.width" value="800"/>
+ <property name="javafx.height" value="600"/>
+ </target>
+
+ <target name="-set-update-mode-background" depends="-check-project" if="update-mode-background">
+ <property name="update-mode" value="background"/>
+ </target>
+ <target name="-set-update-mode-eager" depends="-check-project" unless="update-mode-background">
+ <property name="update-mode" value="eager"/>
+ </target>
+
+ <target name="-set-permissions-elevated" depends="-check-project" if="permissions-elevated">
+ <property name="permissions.elevated" value="true"/>
+ </target>
+ <target name="-reset-permissions-elevated" depends="-check-project" unless="permissions-elevated">
+ <property name="permissions.elevated" value="false"/>
+ </target>
+
+ <target name="-set-binary-css" depends="-check-project,-init-css-conversion" if="do.copy.binary.css">
+ <property name="css-include-ext" value="bss"/>
+ <property name="css-exclude-ext" value="css"/>
+ </target>
+ <target name="-unset-binary-css" depends="-check-project,-init-css-conversion" unless="do.copy.binary.css">
+ <property name="css-include-ext" value="css"/>
+ <property name="css-exclude-ext" value="bss"/>
+ </target>
+ <target name="-copy-binary-css" depends="-init-css-conversion,-set-binary-css,-unset-binary-css,-copy-binary-css-bypass,-copy-binary-css-impl"/>
+ <target name="-init-css-conversion" depends="-check-project,-check-jdk-version">
+ <fileset id="cssfiles" dir="${basedir}${file.separator}${build.classes.dir}">
+ <include name="**${file.separator}*.css"/>
+ </fileset>
+ <pathconvert refid="cssfiles" property="cssfileset.notempty" setonempty="false"/>
+ <condition property="do.copy.binary.css">
+ <and>
+ <isset property="binary-encode-css"/>
+ <isset property="cssfileset.notempty"/>
+ <not><isset property="have-jdk7-css2bin-bug"/></not>
+ </and>
+ </condition>
+ <condition property="do.bypass.binary.css">
+ <and>
+ <isset property="binary-encode-css"/>
+ <isset property="cssfileset.notempty"/>
+ <isset property="have-jdk7-css2bin-bug"/>
+ </and>
+ </condition>
+ <echo message="do.copy.binary.css = ${do.copy.binary.css}" level="verbose"/>
+ <echo message="do.bypass.binary.css = ${do.bypass.binary.css}" level="verbose"/>
+ </target>
+ <target name="-copy-binary-css-bypass" depends="-init-css-conversion" if="do.bypass.binary.css">
+ <echo message="Warning: Bypassing FX CSS to BSS conversion due to a bug in <fx:csstobin> task in current JDK platform" level="warning"/>
+ </target>
+ <target name="-copy-binary-css-impl" depends="-init-css-conversion" if="do.copy.binary.css">
+ <property name="cssfileslist" refid="cssfiles"/>
+ <echo message="css files to binary convert: " level="verbose">${cssfileslist}</echo>
+ <fx:csstobin outdir="${basedir}${file.separator}${build.classes.dir}">
+ <fileset refid="cssfiles"/>
+ </fx:csstobin>
+ </target>
+
+
+ <!-- Copy dependent libraries -->
+
+ <!-- Note: target "-jfx-copylibs" is referenced from NB 7.1 build-impl.xml -->
+ <target name="-jfx-copylibs" depends="init,compile,-pre-pre-jar,-pre-jar,-jfx-copylibs-warning" unless="fallback.no.javascript">
+ <jfx-copylibs-js-impl/>
+ </target>
+ <target name="-jfx-copylibs-warning" if="fallback.no.javascript">
+ <echo message="Warning: Dependent Libraries copy (-jfx-copylibs) skipped in fallback build mode due to JDK missing JavaScript support."/>
+ </target>
+ <macrodef name="jfx-copylibs-js-impl">
+ <sequential>
+ <local name="run.classpath.without.build.classes.and.dist.dir"/>
+ <pathconvert property="run.classpath.without.build.classes.and.dist.dir">
+ <path path="${run.classpath}"/>
+ <map from="${basedir}${file.separator}${build.classes.dir}" to=""/>
+ <map from="${basedir}${file.separator}${dist.jar}" to=""/>
+ <map from="${javafx.runtime}${file.separator}lib${file.separator}jfxrt.jar" to=""/>
+ <map from="${javafx.runtime}${file.separator}lib${file.separator}deploy.jar" to=""/>
+ <map from="${javafx.runtime}${file.separator}lib${file.separator}javaws.jar" to=""/>
+ <map from="${javafx.runtime}${file.separator}lib${file.separator}plugin.jar" to=""/>
+ </pathconvert>
+ <!-- add possibly missing dependencies at distance 2 (build system logic thus provides transitive closure) -->
+ <local name="run.and.lib.classpath"/>
+ <echo message="JavaScript: -jfx-copylibs" level="verbose"/>
+ <script language="javascript">
+ <![CDATA[
+ var pathConvert = project.createTask("pathconvert");
+ pathConvert.setProperty("run.and.lib.classpath");
+ var classPath = project.getProperty("run.classpath.without.build.classes.and.dist.dir");
+ var fileSeparator = project.getProperty("file.separator");
+ if(classPath != null) {
+ var classPathCopy = pathConvert.createPath();
+ classPathCopy.setPath(classPath);
+ if(classPath.indexOf(";") != -1) {
+ var pathArray = classPath.split(";");
+ } else {
+ var pathArray = classPath.split(":");
+ }
+ var added = "";
+ for (var i=0; i<pathArray.length; i++) {
+ var index = pathArray[i].lastIndexOf(fileSeparator);
+ if (index >=0) {
+ var onePath = pathArray[i].substr(0,index+1) + "lib";
+ var oneDir = new java.io.File(onePath);
+ if(oneDir.exists()) {
+ var fs = project.createDataType("fileset");
+ fs.setDir( oneDir );
+ fs.setIncludes("*.jar");
+ var ds = fs.getDirectoryScanner(project);
+ var srcFiles = ds.getIncludedFiles();
+ for (j=0; j<srcFiles.length; j++) {
+ if(classPath.indexOf(srcFiles[j]) == -1 && added.indexOf(srcFiles[j]) == -1) {
+ var path = pathConvert.createPath();
+ path.setPath(onePath + fileSeparator + srcFiles[j]);
+ added += srcFiles[j];
+ }
+ }
+ }
+ }
+ }
+ }
+ pathConvert.perform();
+ ]]>
+ </script>
+ <echo message="run.and.lib.classpath = ${run.and.lib.classpath}" level="verbose"/>
+ <delete dir="${dist.dir}${file.separator}lib" includeEmptyDirs="true" quiet="true"/>
+ <copy todir="${dist.dir}${file.separator}lib" flatten="true" preservelastmodified="true" overwrite="true">
+ <path>
+ <pathelement path="${run.and.lib.classpath}"/>
+ </path>
+ </copy>
+ </sequential>
+ </macrodef>
+
+ <target name="-copy-external-preloader-jar" depends="-check-project" if="app-with-external-preloader-jar">
+ <copy file="${javafx.preloader.jar.path}" todir="${dist.dir}${file.separator}lib"/>
+ </target>
+
+
+ <!-- Optional classpath re-base of dependent JAR manifests after copy to lib/, required by GlassFish -->
+
+ <!-- Note: target "-rebase-libs" is referenced from NB 7.1 build-impl.xml -->
+ <target name="-rebase-libs" depends="-check-project, -jfx-copylibs, -check-rebase-libs, -rebase-libs-warning" if="do-rebase-lib-jars">
+ <rebase-libs-js-impl/>
+ </target>
+ <target name="-check-rebase-libs">
+ <condition property="do-rebase-lib-jars">
+ <and>
+ <isset property="rebase-lib-jars"/>
+ <not><isset property="fallback.no.javascript"/></not>
+ </and>
+ </condition>
+ <condition property="do-skip-rebase-libs">
+ <and>
+ <isset property="rebase-lib-jars"/>
+ <isset property="fallback.no.javascript"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-rebase-libs-warning" depends="-check-rebase-libs" if="do-skip-rebase-libs">
+ <echo message="Warning: Dependent Libraries JARs rebase (-rebase-libs) skipped in fallback build mode due to JDK missing JavaScript support."/>
+ </target>
+
+ <macrodef name="rebase-libs-js-impl">
+ <sequential>
+ <property name="pp_rebase_dir" value="${basedir}${file.separator}${dist.dir}${file.separator}lib"/>
+ <property name="pp_rebase_fs" value="*.jar"/>
+ <echo message="JavaScript: -rebase-libs-js-impl" level="verbose"/>
+ <script language="javascript">
+ <![CDATA[
+ var dir = project.getProperty("pp_rebase_dir");
+ var fDir = new java.io.File(dir);
+ if( fDir.exists() ) {
+ var callTask = project.createTask("antcall");
+ callTask.setTarget("-rebase-libs-macro-call");
+ var param = callTask.createParam();
+ param.setName("jar.file.to.rebase");
+ var includes = project.getProperty("pp_rebase_fs");
+ var fs = project.createDataType("fileset");
+ fs.setDir( fDir );
+ fs.setIncludes(includes);
+ var ds = fs.getDirectoryScanner(project);
+ var srcFiles = ds.getIncludedFiles();
+ for (i=0; i<srcFiles.length; i++) {
+ param.setValue(dir + "${file.separator}" + srcFiles[i]);
+ callTask.perform();
+ }
+ }
+ ]]>
+ </script>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="rebase-lib">
+ <attribute name="jarfile"/>
+ <sequential>
+ <local name="tmpdir"/>
+ <property name="tmpdir" value="${java.io.tmpdir}${file.separator}${user.name}_${ant.project.name}_rebase" />
+ <echo message="tmpdir = ${tmpdir}" level="verbose"/>
+ <delete dir="${tmpdir}" quiet="true"/>
+ <mkdir dir="${tmpdir}"/>
+ <unzip src="@{jarfile}" dest="${tmpdir}">
+ <patternset>
+ <include name="META-INF${file.separator}MANIFEST.MF"/>
+ </patternset>
+ </unzip>
+ <local name="manifest.file.temp"/>
+ <property name="manifest.file.temp" value="${tmpdir}${file.separator}META-INF${file.separator}MANIFEST.MF" />
+ <echo message="manifest.file.temp = ${manifest.file.temp}" level="verbose"/>
+ <!-- edited manifest file -->
+ <local name="manifest.file.temp.new"/>
+ <property name="manifest.file.temp.new" value="${manifest.file.temp}_new" />
+ <echo message="manifest.file.temp.new = ${manifest.file.temp.new}" level="verbose"/>
+ <echo message="JavaScript: rebase-lib" level="verbose"/>
+ <script language="javascript">
+ <![CDATA[
+ var UTF_8 = "UTF-8";
+ var ATTR_CLASS_PATH = "Class-Path";
+ var ATTR_CLASS_PATH_FX = "JavaFX-Class-Path";
+ function isSigned(manifest) {
+ var sections = manifest.getSectionNames();
+ while(sections.hasMoreElements()) {
+ var sectionname = sections.nextElement();
+ var section = manifest.getSection(sectionname);
+ if(section != null) {
+ var sectionKeys = section.getAttributeKeys();
+ while (sectionKeys.hasMoreElements()) {
+ var element = sectionKeys.nextElement();
+ if (element.endsWith("-Digest") || element.endsWith("-digest")) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+ var src = project.getProperty("manifest.file.temp");
+ var srf = new java.io.File(src);
+ try {
+ var fis = new java.io.FileInputStream(srf);
+ try {
+ var isr = new java.io.InputStreamReader(fis, UTF_8);
+ try {
+ var manifest = new org.apache.tools.ant.taskdefs.Manifest(isr);
+ } finally {
+ isr.close();
+ }
+ } finally {
+ fis.close();
+ }
+ } catch(e) {
+ var manifest = null;
+ }
+ if(manifest != null) {
+ if(isSigned(manifest)) {
+ println("Warning: Signed JAR can not be rebased.");
+ } else {
+ var mainSection = manifest.getMainSection();
+ var classPath = mainSection.getAttributeValue(ATTR_CLASS_PATH);
+ if (classPath != null) {
+ var classPathAttr = ATTR_CLASS_PATH;
+ } else {
+ classPath = mainSection.getAttributeValue(ATTR_CLASS_PATH_FX);
+ if(classPath != null) {
+ var classPathAttr = ATTR_CLASS_PATH_FX;
+ }
+ }
+ if(classPath != null) {
+ var result = new java.lang.StringBuilder();
+ var changed = false;
+ var pathArray = classPath.split(" ");
+ for (var i=0; i<pathArray.length; i++) {
+ if (result.length() > 0) {
+ result.append(' ');
+ }
+ var index = pathArray[i].lastIndexOf('/');
+ if (index >=0 && index < pathArray[i].length()-1) {
+ pathArray[i] = pathArray[i].substring(index+1);
+ changed = true;
+ }
+ result.append(pathArray[i]);
+ }
+ mainSection.removeAttribute(classPathAttr);
+ mainSection.addAttributeAndCheck(new org.apache.tools.ant.taskdefs.Manifest.Attribute(classPathAttr, result.toString()));
+ var tgt = project.getProperty("manifest.file.temp.new");
+ var tgf = new java.io.File(tgt);
+ try {
+ var fos = new java.io.FileOutputStream(tgf);
+ try {
+ var osw = new java.io.OutputStreamWriter(fos, UTF_8);
+ try {
+ var manifestOut = new java.io.PrintWriter(osw);
+ manifest.write(manifestOut);
+ manifestOut.close();
+ } finally {
+ osw.close();
+ }
+ } finally {
+ fos.close();
+ }
+ } catch(e) {
+ println("Warning: problem storing rebased manifest file.");
+ }
+ }
+ }
+ }
+ ]]>
+ </script>
+ <antcall target="-move-new-manifest-if-exists">
+ <param name="move.file.from" value="${manifest.file.temp.new}"/>
+ <param name="move.file.to" value="${manifest.file.temp}"/>
+ </antcall>
+ <zip destfile="@{jarfile}" basedir="${tmpdir}" update="true"/>
+ <delete dir="${tmpdir}" quiet="true"/>
+ </sequential>
+ </macrodef>
+
+ <target name="-new-temp-mainfest-existence">
+ <condition property="new-temp-manifest-exists">
+ <available file="${move.file.from}"/>
+ </condition>
+ <echo message="new-temp-manifest-exists = ${new-temp-manifest-exists}" level="verbose"/>
+ </target>
+
+ <target name="-move-new-manifest-if-exists" depends="-new-temp-mainfest-existence" if="new-temp-manifest-exists">
+ <move file="${move.file.from}" tofile="${move.file.to}" failonerror="false"/>
+ </target>
+
+ <target name="-rebase-libs-macro-call">
+ <echo message="Rebase jarfile = ${jar.file.to.rebase}" level="verbose"/>
+ <rebase-lib jarfile="${jar.file.to.rebase}"/>
+ </target>
+
+
+ <!-- Main Deployment Target -->
+
+ <!-- Note: target "jfx-deployment" is referenced from NB 7.1+ build-impl.xml -->
+ <target name="jfx-deployment" depends="-check-jfx-deployment-launch,-do-jfx-deployment-script,-do-jfx-deployment-noscript" if="jfx-deployment-available"/>
+
+ <target name="-check-dist-lib-exists">
+ <deploy-defines/>
+ <available file="${jfx.deployment.dir}${file.separator}lib" type="dir" property="dist.lib.exists"/>
+ </target>
+ <target name="-check-jfx-deployment-jar-current-nolib" depends="-check-dist-lib-exists" unless="dist.lib.exists">
+ <uptodate property="jfx-deployment-jar-current" targetfile="${jfx.deployment.dir}${file.separator}${jfx.deployment.jar}" >
+ <srcfiles dir="${basedir}${file.separator}${build.classes.dir}" includes="**${file.separator}*"/>
+ <srcfiles dir="${basedir}${file.separator}nbproject" includes="**${file.separator}*"/>
+ </uptodate>
+ </target>
+ <target name="-check-jfx-deployment-jar-current-lib" depends="-check-dist-lib-exists" if="dist.lib.exists">
+ <uptodate property="jfx-deployment-jar-current" targetfile="${jfx.deployment.dir}${file.separator}${jfx.deployment.jar}" >
+ <srcfiles dir="${basedir}${file.separator}${build.classes.dir}" includes="**${file.separator}*"/>
+ <srcfiles dir="${jfx.deployment.dir}${file.separator}lib" includes="**${file.separator}*"/>
+ <srcfiles dir="${basedir}${file.separator}nbproject" includes="**${file.separator}*"/>
+ </uptodate>
+ </target>
+ <target name="-check-jfx-deployment-launch" depends="-check-jfx-deployment,-check-jfx-deployment-jar-current-nolib,-check-jfx-deployment-jar-current-lib">
+ <condition property="do-jfx-deployment-script">
+ <and>
+ <isset property="jfx-deployment-available"/>
+ <not><isset property="fallback.no.javascript"/></not>
+ <not><isset property="jfx-deployment-jar-current"/></not>
+ </and>
+ </condition>
+ <condition property="do-jfx-deployment-noscript">
+ <and>
+ <isset property="jfx-deployment-available"/>
+ <isset property="fallback.no.javascript"/>
+ <not><isset property="jfx-deployment-jar-current"/></not>
+ </and>
+ </condition>
+ </target>
+ <target name="-do-jfx-deployment-script" depends="-check-jfx-deployment-launch" if="do-jfx-deployment-script">
+ <antcall target="jfx-deployment-script"/>
+ </target>
+ <target name="-do-jfx-deployment-noscript" depends="-check-jfx-deployment-launch" if="do-jfx-deployment-noscript">
+ <antcall target="jfx-deployment-noscript"/>
+ </target>
+
+ <target name="jfx-deployment-script" depends="-check-jfx-deployment,-check-project,
+ -swing-api-warning,-icon-warning,
+ -set-dimensions,-reset-dimensions,-set-update-mode-background,-set-update-mode-eager,
+ -set-permissions-elevated,-reset-permissions-elevated,
+ -copy-external-preloader-jar,-copy-binary-css,
+ -deploy-app-sign-nopreloader-notemplate,
+ -deploy-app-sign-preloader-notemplate,
+ -deploy-app-sign-nopreloader-template,
+ -deploy-app-sign-preloader-template,
+ -deploy-app-sign-nopreloader-notemplate-swing,
+ -deploy-app-sign-nopreloader-template-swing,
+ -deploy-app-nosign-nopreloader-notemplate,
+ -deploy-app-nosign-preloader-notemplate,
+ -deploy-app-nosign-nopreloader-template,
+ -deploy-app-nosign-preloader-template,
+ -deploy-app-nosign-nopreloader-notemplate-swing,
+ -deploy-app-nosign-nopreloader-template-swing"
+ if="jfx-deployment-available">
+ </target>
+
+ <target name="jfx-deployment-noscript" depends="-check-jfx-deployment,-check-project,
+ -swing-api-warning,-icon-warning,
+ -set-dimensions,-reset-dimensions,-set-update-mode-background,-set-update-mode-eager,
+ -set-permissions-elevated,-reset-permissions-elevated,
+ -copy-external-preloader-jar,-copy-binary-css,
+ -fallback-deploy-app-sign-nopreloader-notemplate,
+ -fallback-deploy-app-sign-preloader-notemplate,
+ -fallback-deploy-app-sign-nopreloader-template,
+ -fallback-deploy-app-sign-preloader-template,
+ -fallback-deploy-app-sign-nopreloader-notemplate-swing,
+ -fallback-deploy-app-sign-nopreloader-template-swing,
+ -fallback-deploy-app-nosign-nopreloader-notemplate,
+ -fallback-deploy-app-nosign-preloader-notemplate,
+ -fallback-deploy-app-nosign-nopreloader-template,
+ -fallback-deploy-app-nosign-preloader-template,
+ -fallback-deploy-app-nosign-nopreloader-notemplate-swing,
+ -fallback-deploy-app-nosign-nopreloader-template-swing"
+ if="jfx-deployment-available">
+ </target>
+
+
+ <!-- Security / Signing -->
+
+ <target name="-unavailable-signjars-task" depends="-check-jfx-deployment" unless="jfx-deployment-available">
+ <echo message="Warning: Task required to sign JAR file is missing, check the availability of JavaFX 2.0 deployment tasks. JAR files will not be signed."/>
+ </target>
+
+ <target name="-security-props-check">
+ <condition property="javafx.signed.true">
+ <istrue value="${javafx.signing.enabled}"/>
+ </condition>
+ </target>
+
+ <target name="-check-signing-possible" depends="-security-props-check,-check-jfx-deployment,-unavailable-signjars-task">
+ <condition property="javafx.signed.true+signjars.task.available">
+ <and>
+ <isset property="javafx.signed.true"/>
+ <isset property="jfx-deployment-available"/>
+ </and>
+ </condition>
+ </target>
+
+ <target name="-javafx-init-keystore" depends="-check-signing-possible,-javafx-init-signing,-javafx-init-keystore1,-javafx-init-keystore2,-check-keystore-exists"
+ if="javafx.signed.true+signjars.task.available" unless="javafx.signjar.keystore.exists">
+ <property name="javafx.signjar.vendor" value="CN=${application.vendor}"/>
+ <echo message="Going to create default keystore in ${javafx.signjar.keystore}"/>
+ <genkey dname="${javafx.signjar.vendor}" alias="${javafx.signjar.alias}" keystore="${javafx.signjar.keystore}"
+ storepass="${javafx.signjar.storepass}" keypass="${javafx.signjar.keypass}"/>
+ </target>
+
+ <target name="-check-keystore-exists">
+ <available property="javafx.signjar.keystore.exists" file="${javafx.signjar.keystore}"/>
+ </target>
+
+ <target name="-javafx-init-signing">
+ <condition property="generated.key.signing">
+ <equals arg1="${javafx.signing.type}" arg2="self" trim="true"/>
+ </condition>
+ </target>
+
+ <target name="-javafx-init-keystore1" depends="-javafx-init-signing" if="generated.key.signing">
+ <property name="javafx.signjar.keystore" value="${basedir}${file.separator}build${file.separator}nb-jfx.jks" />
+ <property name="javafx.signjar.storepass" value="storepass"/>
+ <property name="javafx.signjar.keypass" value="keypass"/>
+ <property name="javafx.signjar.alias" value="nb-jfx"/>
+ </target>
+
+ <target name="-javafx-init-keystore2" depends="-javafx-init-signing" unless="generated.key.signing">
+ <property name="javafx.signjar.keystore" value="${javafx.signing.keystore}" />
+ <property name="javafx.signjar.storepass" value="${javafx.signing.keystore.password}"/>
+ <property name="javafx.signjar.keypass" value="${javafx.signing.keyalias.password}"/>
+ <property name="javafx.signjar.alias" value="${javafx.signing.keyalias}"/>
+ </target>
+
+
+ <!-- Project Deployment Macros -->
+
+ <macrodef name="deploy-defines">
+ <sequential>
+ <basename property="jfx.deployment.jar" file="${dist.jar}"/>
+ <property name="jfx.deployment.dir" location="${dist.dir}"/>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="deploy-preprocess">
+ <sequential>
+ <delete includeEmptyDirs="true" quiet="true">
+ <fileset dir="${jfx.deployment.dir}${file.separator}lib">
+ <exclude name="**${file.separator}*.jar"/>
+ </fileset>
+ </delete>
+ </sequential>
+ </macrodef>
+
+ <!-- fx:jar scripted call enables passing of arbitrarily long list of params and fx-version dependent behavior -->
+ <macrodef name="deploy-jar">
+ <sequential>
+ <antcall target="-pre-jfx-jar"/>
+ <echo message="javafx.ant.classpath = ${javafx.ant.classpath}" level="verbose"/>
+ <typedef name="fx_jar" classname="com.sun.javafx.tools.ant.FXJar" classpath="${javafx.ant.classpath}"/>
+ <echo message="Launching <fx:jar> task from ${ant-javafx.jar.location}" level="info"/>
+ <property name="pp_jar_destfile" value="${jfx.deployment.dir}${file.separator}${jfx.deployment.jar}"/>
+ <property name="pp_jar_buildclasses" value="${basedir}${file.separator}${build.classes.dir}"/>
+ <property name="pp_jar_cssbss" value="**${file.separator}*.${css-exclude-ext}"/>
+ <property name="pp_jar_dir" value="${jfx.deployment.dir}"/>
+ <property name="pp_jar_fs1" value="lib${file.separator}${javafx.preloader.jar.filename}"/>
+ <property name="pp_jar_fs2" value="lib${file.separator}*.jar"/>
+ <echo message="deploy_jar: pp_jar_destfile = ${pp_jar_destfile}" level="verbose"/>
+ <echo message="deploy_jar: pp_jar_buildclasses = ${pp_jar_buildclasses}" level="verbose"/>
+ <echo message="deploy_jar: pp_jar_cssbss = ${pp_jar_cssbss}" level="verbose"/>
+ <echo message="deploy_jar: pp_jar_dir = ${pp_jar_dir}" level="verbose"/>
+ <echo message="deploy_jar: pp_jar_fs1 = ${pp_jar_fs1}" level="verbose"/>
+ <echo message="deploy_jar: pp_jar_fs2 = ${pp_jar_fs2}" level="verbose"/>
+ <echo message="JavaScript: deploy-jar" level="verbose"/>
+ <script language="javascript">
+ <![CDATA[
+ var S = java.io.File.separator;
+ var JFXPAR = "javafx.param";
+ var JFXPARN = "name";
+ var JFXPARV = "value";
+ var JFXLAZY = "download.mode.lazy.jar";
+ var withpreloader = project.getProperty("app-with-preloader");
+ var fx_ant_api_1_1 = project.getProperty("have-fx-ant-api-1.1");
+ var fx_ant_api_1_2 = project.getProperty("have-fx-ant-api-1.2");
+ var fx_in_swing_app = project.getProperty("fx-in-swing-app");
+
+ // get jars with lazy download mode property set
+ function getLazyJars() {
+ var jars = new Array();
+ var keys = project.getProperties().keys();
+ while(keys.hasMoreElements()) {
+ var pn = keys.nextElement();
+ if(pn.substr(0,JFXLAZY.length) == JFXLAZY) {
+ var fname = pn.substring(JFXLAZY.length+1);
+ jars.push(fname);
+ }
+ }
+ return jars.length > 0 ? jars : null;
+ }
+ // set download mode of dependent libraries
+ function setDownloadMode(fsEager, fsLazy, jars) {
+ for(i = 0; i < jars.length; i++) {
+ fsEager.setExcludes("lib" + S + jars[i]);
+ fsLazy.setIncludes("lib" + S + jars[i]);
+ }
+ }
+
+ // fx:jar
+ var jar = project.createTask("fx_jar");
+ jar.setProject(project);
+ var destfile = project.getProperty("pp_jar_destfile");
+ jar.setDestfile(destfile);
+
+ // fx:application
+ var app = jar.createApplication();
+ app.setProject(project);
+ var title = project.getProperty("application.title");
+ if(fx_in_swing_app == "true" && fx_ant_api_1_2 == "true") {
+ var mainclass = project.getProperty("main.class");
+ app.setToolkit("swing");
+ } else {
+ var mainclass = project.getProperty("javafx.main.class");
+ }
+ var fallback = project.getProperty("javafx.fallback.class");
+ app.setName(title);
+ app.setMainClass(mainclass);
+ app.setFallbackClass(fallback);
+ if(withpreloader == "true") {
+ preloaderclass = project.getProperty("javafx.preloader.class");
+ app.setPreloaderClass(preloaderclass);
+ }
+ // fx:param, fx:argument
+ var keys = project.getProperties().keys();
+ while(keys.hasMoreElements()) {
+ var pn = keys.nextElement();
+ if(pn.substr(0,JFXPAR.length) == JFXPAR && pn.indexOf(JFXPARN) == (pn.length()-JFXPARN.length)) {
+ var propn = project.getProperty(pn);
+ if(propn != null && propn.length() > 0) {
+ var pv = pn.substr(0,pn.indexOf(JFXPARN)) + JFXPARV;
+ var propv = project.getProperty(pv);
+ if(propv != null && propv.length() > 0) {
+ var par = app.createParam();
+ par.setName(propn);
+ par.setValue(propv);
+ } else {
+ if(fx_ant_api_1_1 == "true") {
+ var arg = app.createArgument();
+ arg.addText(propn);
+ }
+ }
+ }
+ }
+ }
+
+ // fx:resources
+ var res = jar.createResources();
+ res.setProject(project);
+ var pdir = project.getProperty("pp_jar_dir");
+ if(withpreloader == "true") {
+ var f1 = res.createFileSet();
+ f1.setProject(project);
+ f1.setDir(new java.io.File(pdir));
+ var i1 = project.getProperty("pp_jar_fs1");
+ f1.setIncludes(i1);
+ f1.setRequiredFor("preloader");
+ var f2 = res.createFileSet();
+ f2.setProject(project);
+ f2.setDir(new java.io.File(pdir));
+ var i2a = project.getProperty("jfx.deployment.jar");
+ var i2b = project.getProperty("pp_jar_fs2");
+ var e2c = project.getProperty("pp_jar_fs1");
+ f2.setIncludes(i2a);
+ f2.setIncludes(i2b);
+ f2.setExcludes(e2c);
+ f2.setRequiredFor("startup");
+ var lazyjars = getLazyJars();
+ if(lazyjars != null) {
+ var f3 = res.createFileSet();
+ f3.setProject(project);
+ f3.setDir(new java.io.File(pdir));
+ f3.setRequiredFor("runtime");
+ setDownloadMode(f2,f3,lazyjars);
+ }
+ } else {
+ var fn = res.createFileSet();
+ fn.setProject(project);
+ fn.setDir(new java.io.File(pdir));
+ var ia = project.getProperty("jfx.deployment.jar");
+ var ib = project.getProperty("pp_jar_fs2");
+ fn.setIncludes(ia);
+ fn.setIncludes(ib);
+ fn.setRequiredFor("startup");
+ var lazyjars = getLazyJars();
+ if(lazyjars != null) {
+ var fn2 = res.createFileSet();
+ fn2.setProject(project);
+ fn2.setDir(new java.io.File(pdir));
+ fn2.setRequiredFor("runtime");
+ setDownloadMode(fn,fn2,lazyjars);
+ }
+ }
+
+ // fileset to exclude *.css or *.bss
+ var fs = jar.createFileSet();
+ fs.setProject(project);
+ var buildcls = project.getProperty("pp_jar_buildclasses");
+ var exc = project.getProperty("pp_jar_cssbss");
+ fs.setDir(new java.io.File(buildcls));
+ fs.setExcludes(exc);
+
+ // manifest
+ var man = jar.createManifest();
+ var a1val = project.getProperty("application.vendor");
+ var a1 = new org.apache.tools.ant.taskdefs.Manifest.Attribute();
+ a1.setName("Implementation-Vendor");
+ a1.setValue(a1val);
+ man.addConfiguredAttribute(a1);
+ var a2val = project.getProperty("application.title");
+ var a2 = new org.apache.tools.ant.taskdefs.Manifest.Attribute();
+ a2.setName("Implementation-Title");
+ a2.setValue(a2val);
+ man.addConfiguredAttribute(a2);
+ var a3 = new org.apache.tools.ant.taskdefs.Manifest.Attribute();
+ a3.setName("Implementation-Version");
+ a3.setValue("1.0");
+ man.addConfiguredAttribute(a3);
+
+ jar.perform();
+ ]]>
+ </script>
+ <antcall target="-post-jfx-jar"/>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="deploy-sign">
+ <sequential>
+ <echo message="keystore=${javafx.signjar.keystore}" level="verbose"/>
+ <echo message="storepass=${javafx.signjar.storepass}" level="verbose"/>
+ <echo message="alias=${javafx.signjar.alias}" level="verbose"/>
+ <echo message="keypass=${javafx.signjar.keypass}" level="verbose"/>
+ <signjar keystore="${javafx.signjar.keystore}"
+ storepass="${javafx.signjar.storepass}"
+ alias="${javafx.signjar.alias}"
+ keypass="${javafx.signjar.keypass}">
+ <fileset dir="${jfx.deployment.dir}">
+ <include name="${jfx.deployment.jar}"/>
+ <include name="lib${file.separator}*.jar"/>
+ </fileset>
+ </signjar>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="deploy-sign-preloader">
+ <sequential>
+ <echo message="keystore=${javafx.signjar.keystore}" level="verbose"/>
+ <echo message="storepass=${javafx.signjar.storepass}" level="verbose"/>
+ <echo message="alias=${javafx.signjar.alias}" level="verbose"/>
+ <echo message="keypass=${javafx.signjar.keypass}" level="verbose"/>
+ <signjar keystore="${javafx.signjar.keystore}"
+ storepass="${javafx.signjar.storepass}"
+ alias="${javafx.signjar.alias}"
+ keypass="${javafx.signjar.keypass}">
+ <fileset dir="${jfx.deployment.dir}">
+ <include name="lib${file.separator}${javafx.preloader.jar.filename}"/>
+ </fileset>
+ </signjar>
+ <signjar keystore="${javafx.signjar.keystore}"
+ storepass="${javafx.signjar.storepass}"
+ alias="${javafx.signjar.alias}"
+ keypass="${javafx.signjar.keypass}">
+ <fileset dir="${jfx.deployment.dir}">
+ <include name="${jfx.deployment.jar}"/>
+ <include name="lib${file.separator}*.jar"/>
+ <exclude name="lib${file.separator}${javafx.preloader.jar.filename}"/>
+ </fileset>
+ </signjar>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="deploy-process-template">
+ <sequential>
+ <echo message="javafx.run.htmltemplate = ${javafx.run.htmltemplate}" level="verbose"/>
+ <pathconvert property="javafx.run.htmltemplate.processed">
+ <path path="${javafx.run.htmltemplate}"/>
+ <mapper>
+ <chainedmapper>
+ <flattenmapper/>
+ <globmapper from="*" to="${jfx.deployment.dir}${file.separator}*" casesensitive="no"/>
+ </chainedmapper>
+ </mapper>
+ </pathconvert>
+ <echo message="javafx.run.htmltemplate.processed = ${javafx.run.htmltemplate.processed}" level="verbose"/>
+ </sequential>
+ </macrodef>
+
+ <!-- fx:deploy scripted call enables passing of arbitrarily long lists of params, vmoptions and callbacks and fx-version dependent behavior -->
+ <macrodef name="deploy-deploy">
+ <sequential>
+ <antcall target="-pre-jfx-deploy"/>
+ <antcall target="-call-pre-jfx-native"/>
+ <echo message="javafx.ant.classpath = ${javafx.ant.classpath}" level="verbose"/>
+ <typedef name="fx_deploy" classname="com.sun.javafx.tools.ant.DeployFXTask" classpath="${javafx.ant.classpath}"/>
+ <echo message="Launching <fx:deploy> task from ${ant-javafx.jar.location}" level="info"/>
+ <property name="pp_deploy_dir" value="${jfx.deployment.dir}"/>
+ <property name="pp_deploy_fs1" value="lib${file.separator}${javafx.preloader.jar.filename}"/>
+ <property name="pp_deploy_fs2" value="lib${file.separator}*.jar"/>
+ <echo message="deploy_deploy: pp_deploy_dir = ${pp_deploy_dir}" level="verbose"/>
+ <echo message="deploy_deploy: pp_deploy_fs1 = ${pp_deploy_fs1}" level="verbose"/>
+ <echo message="deploy_deploy: pp_deploy_fs2 = ${pp_deploy_fs2}" level="verbose"/>
+ <echo message="JavaScript: deploy-deploy" level="verbose"/>
+ <script language="javascript">
+ <![CDATA[
+ function isTrue(prop) {
+ return prop != null &&
+ (prop.toLowerCase()=="true" || prop.toLowerCase()=="yes" || prop.toLowerCase()=="on");
+ }
+ var S = java.io.File.separator;
+ var JFXPAR = "javafx.param";
+ var JFXPARN = "name";
+ var JFXPARV = "value";
+ var JFXCALLB = "javafx.jscallback";
+ var JFXLAZY = "download.mode.lazy.jar";
+ var withpreloader = project.getProperty("app-with-preloader");
+ var fx_ant_api_1_1 = project.getProperty("have-fx-ant-api-1.1");
+ var fx_ant_api_1_2 = project.getProperty("have-fx-ant-api-1.2");
+ var fx_in_swing_app = project.getProperty("fx-in-swing-app");
+
+ // get jars with lazy download mode property set
+ function getLazyJars() {
+ var jars = new Array();
+ var keys = project.getProperties().keys();
+ while(keys.hasMoreElements()) {
+ var pn = keys.nextElement();
+ if(pn.substr(0,JFXLAZY.length) == JFXLAZY) {
+ var fname = pn.substring(JFXLAZY.length+1);
+ jars.push(fname);
+ }
+ }
+ return jars.length > 0 ? jars : null;
+ }
+ // set download mode of dependent libraries
+ function setDownloadMode(fsEager, fsLazy, jars) {
+ for(i = 0; i < jars.length; i++) {
+ fsEager.setExcludes("lib" + S + jars[i]);
+ fsLazy.setIncludes("lib" + S + jars[i]);
+ }
+ }
+
+ // fx:deploy
+ var deploy = project.createTask("fx_deploy");
+ deploy.setProject(project);
+ var width = project.getProperty("javafx.width");
+ var height = project.getProperty("javafx.height");
+ var outdir = project.getProperty("jfx.deployment.dir");
+ var embedJNLP = project.getProperty("javafx.deploy.embedJNLP");
+ var updatemode = project.getProperty("update-mode");
+ var outfile = project.getProperty("application.title");
+ var includeDT = project.getProperty("javafx.deploy.includeDT");
+ var offline = project.getProperty("javafx.deploy.allowoffline");
+ deploy.setWidth(width);
+ deploy.setHeight(height);
+ deploy.setOutdir(outdir);
+ deploy.setEmbedJNLP(isTrue(embedJNLP));
+ deploy.setUpdateMode(updatemode);
+ deploy.setOutfile(outfile);
+ deploy.setIncludeDT(isTrue(includeDT));
+ if(offline != null) {
+ if(fx_ant_api_1_1 == "true") {
+ deploy.setOfflineAllowed(isTrue(offline));
+ } else {
+ println("Warning: offlineAllowed not supported by this version of JavaFX SDK deployment Ant task. Please upgrade JavaFX to 2.0.2 or higher.");
+ }
+ }
+ // native packaging (time consuming, thus applied in explicit build only)
+ var nativeEnabled = project.getProperty("do.build.native.package");
+ var nativeType = project.getProperty("javafx.native.bundling.type");
+ var projStateRun = project.getProperty("project.state.running");
+ var projStateDbg = project.getProperty("project.state.debugging");
+ var projStatePrf = project.getProperty("project.state.profiling");
+ if(isTrue(nativeEnabled) && nativeType != null && nativeType != "none") {
+ if(!isTrue(projStateRun) && !isTrue(projStateDbg) && !isTrue(projStatePrf)) {
+ if(fx_ant_api_1_2 == "true") {
+ deploy.setNativeBundles(nativeType);
+ println("Note: To create native bundles the <fx:deploy> task may require external tools. See JavaFX 2.2+ documentation for details.");
+ println("");
+ println("Launching <fx:deploy> in native packager mode...");
+ } else {
+ println("Warning: Native packaging is not supported by this version of JavaFX SDK deployment Ant task. Please upgrade to JDK 7u6 or higher.");
+ }
+ }
+ }
+
+ // fx:application
+ var app = deploy.createApplication();
+ app.setProject(project);
+ var title = project.getProperty("application.title");
+ if(fx_in_swing_app == "true" && fx_ant_api_1_2 == "true") {
+ var mainclass = project.getProperty("main.class");
+ app.setToolkit("swing");
+ } else {
+ var mainclass = project.getProperty("javafx.main.class");
+ }
+ var fallback = project.getProperty("javafx.fallback.class");
+ app.setName(title);
+ app.setMainClass(mainclass);
+ app.setFallbackClass(fallback);
+ if(withpreloader == "true") {
+ preloaderclass = project.getProperty("javafx.preloader.class");
+ app.setPreloaderClass(preloaderclass);
+ }
+ // fx:param, fx:argument
+ var keys = project.getProperties().keys();
+ while(keys.hasMoreElements()) {
+ var pn = keys.nextElement();
+ if(pn.substr(0,JFXPAR.length) == JFXPAR && pn.indexOf(JFXPARN) == (pn.length()-JFXPARN.length)) {
+ var propn = project.getProperty(pn);
+ if(propn != null && propn.length() > 0) {
+ var pv = pn.substr(0,pn.indexOf(JFXPARN)) + JFXPARV;
+ var propv = project.getProperty(pv);
+ if(propv != null && propv.length() > 0) {
+ var par = app.createParam();
+ par.setName(propn);
+ par.setValue(propv);
+ } else {
+ if(fx_ant_api_1_1 == "true") {
+ var arg = app.createArgument();
+ arg.addText(propn);
+ } else {
+ println("Warning: Unnamed parameters not supported by this version of JavaFX SDK deployment Ant tasks. Upgrade JavaFX to 2.0.2 or higher.");
+ }
+ }
+ }
+ }
+ }
+
+ // fx:resources
+ var res = deploy.createResources();
+ res.setProject(project);
+ var deploydir = project.getProperty("pp_deploy_dir");
+ if(withpreloader == "true") {
+ var f1 = res.createFileSet();
+ f1.setProject(project);
+ f1.setDir(new java.io.File(deploydir));
+ var i1 = project.getProperty("pp_deploy_fs1");
+ f1.setIncludes(i1);
+ f1.setRequiredFor("preloader");
+ var f2 = res.createFileSet();
+ f2.setProject(project);
+ f2.setDir(new java.io.File(deploydir));
+ var i2a = project.getProperty("jfx.deployment.jar");
+ var i2b = project.getProperty("pp_deploy_fs2");
+ var e2c = project.getProperty("pp_deploy_fs1");
+ f2.setIncludes(i2a);
+ f2.setIncludes(i2b);
+ f2.setExcludes(e2c);
+ f2.setRequiredFor("startup");
+ var lazyjars = getLazyJars();
+ if(lazyjars != null) {
+ var f3 = res.createFileSet();
+ f3.setProject(project);
+ f3.setDir(new java.io.File(deploydir));
+ f3.setRequiredFor("runtime");
+ setDownloadMode(f2,f3,lazyjars);
+ }
+ } else {
+ var fn = res.createFileSet();
+ fn.setProject(project);
+ fn.setDir(new java.io.File(deploydir));
+ var ia = project.getProperty("jfx.deployment.jar");
+ var ib = project.getProperty("pp_deploy_fs2");
+ fn.setIncludes(ia);
+ fn.setIncludes(ib);
+ fn.setRequiredFor("startup");
+ var lazyjars = getLazyJars();
+ if(lazyjars != null) {
+ var fn2 = res.createFileSet();
+ fn2.setProject(project);
+ fn2.setDir(new java.io.File(deploydir));
+ fn2.setRequiredFor("runtime");
+ setDownloadMode(fn,fn2,lazyjars);
+ }
+ }
+
+ // fx:info
+ var info = deploy.createInfo();
+ info.setProject(project);
+ var vendor = project.getProperty("application.vendor");
+ var description = project.getProperty("application.desc");
+ info.setTitle(title); // title known from before
+ info.setVendor(vendor);
+ info.setDescription(description);
+ var icon = project.getProperty("javafx.deploy.icon");
+ if(icon != null) {
+ if(fx_ant_api_1_1 == "true") {
+ var iicon = info.createIcon();
+ iicon.setHref(icon);
+ } else {
+ println("Warning: Icon not supported by this version of JavaFX SDK deployment Ant task. Please upgrade JavaFX to 2.0.2 or higher.");
+ }
+ }
+
+ // fx:permissions
+ var perm = deploy.createPermissions();
+ perm.setProject(project);
+ var elev = project.getProperty("permissions.elevated");
+ perm.setElevated(isTrue(elev));
+
+ // fx:preferences
+ var pref = deploy.createPreferences();
+ pref.setProject(project);
+ var scut = project.getProperty("javafx.deploy.adddesktopshortcut");
+ var instp = project.getProperty("javafx.deploy.installpermanently");
+ var smenu = project.getProperty("javafx.deploy.addstartmenushortcut");
+ pref.setShortcut(isTrue(scut));
+ pref.setInstall(isTrue(instp));
+ pref.setMenu(isTrue(smenu));
+
+ // fx:template
+ var templ = project.getProperty("javafx.run.htmltemplate");
+ var templp = project.getProperty("javafx.run.htmltemplate.processed");
+ if(templ != null && templp != null && templ.length() > 0 && templp.length() > 0) {
+ var temp = deploy.createTemplate();
+ temp.setProject(project);
+ temp.setFile(new java.io.File(templ));
+ temp.setTofile(new java.io.File(templp));
+ }
+
+ // fx:platform
+ var plat = deploy.createPlatform();
+ plat.setProject(project);
+ var jvmargs = project.getProperty("run.jvmargs");
+ if(jvmargs != null && jvmargs.length() > 0) {
+ var jvmargss = jvmargs.split(" ");
+ for(i = 0; i < jvmargss.length; i++) {
+ if(jvmargss[i] != null && jvmargss[i].length() > 0) {
+ var vmarg = plat.createJvmarg();
+ vmarg.setValue(jvmargss[i]);
+ }
+ }
+ }
+
+ // fx:callbacks
+ var callbs = deploy.createCallbacks();
+ callbs.setProject(project);
+ var keys = project.getProperties().keys();
+ while(keys.hasMoreElements()) {
+ var pn = keys.nextElement();
+ if(pn.substr(0,JFXCALLB.length) == JFXCALLB) {
+ var prop = project.getProperty(pn);
+ if(prop != null && prop.length() > 0) {
+ var cname = pn.substring(JFXCALLB.length+1);
+ var cb = callbs.createCallback();
+ cb.setProject(project);
+ cb.setName(cname);
+ cb.addText(prop);
+ }
+ }
+ }
+
+ deploy.perform();
+ ]]>
+ </script>
+ <antcall target="-post-jfx-deploy"/>
+ <antcall target="-call-post-jfx-native"/>
+ </sequential>
+ </macrodef>
+
+ <!-- JavaFX SDK 2.0.x and 2.1.x deploy task can not generate pre-FX jnlp which is needed for FX-in-Swing projects-->
+ <macrodef name="deploy-deploy-swing">
+ <sequential>
+ <antcall target="-pre-jfx-deploy"/>
+ <local name="permissions-elevated-token"/>
+ <condition property="permissions-elevated-token" value="${line.separator} <security>${line.separator} <all-permissions/>${line.separator} </security>" else="">
+ <isset property="permissions-elevated"/>
+ </condition>
+ <local name="offline-allowed-token"/>
+ <condition property="offline-allowed-token" value="${line.separator} <offline-allowed/>" else="">
+ <isset property="offline-allowed"/>
+ </condition>
+ <local name="update-mode-background-token"/>
+ <condition property="update-mode-background-token" value="background" else="always">
+ <isset property="update-mode-background"/>
+ </condition>
+ <local name="html-template-processed-available"/>
+ <condition property="html-template-processed-available">
+ <and>
+ <isset property="javafx.run.htmltemplate.processed"/>
+ <not>
+ <equals arg1="${javafx.run.htmltemplate.processed}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <local name="javafx.deploy.icon.basename"/>
+ <basename property="javafx.deploy.icon.basename" file="${javafx.deploy.icon}"/>
+ <local name="local-icon-filename-available"/>
+ <condition property="local-icon-filename-available">
+ <and>
+ <isset property="icon-available"/>
+ <isset property="javafx.deploy.icon.basename"/>
+ <not><equals arg1="${javafx.deploy.icon.basename}" arg2=""/></not>
+ <not><contains string="${javafx.deploy.icon.basename}" substring="$${javafx" casesensitive="false"/></not>
+ <not><contains string="${javafx.deploy.icon}" substring="http:" casesensitive="false"/></not>
+ </and>
+ </condition>
+ <local name="icon-token"/>
+ <condition property="icon-token" value="${line.separator} <icon href="${javafx.deploy.icon.basename}" kind="default"/>">
+ <isset property="local-icon-filename-available"/>
+ </condition>
+ <condition property="icon-token" value="${line.separator} <icon href="${javafx.deploy.icon}" kind="default"/>" else="">
+ <isset property="icon-available"/>
+ </condition>
+ <basename property="dist.filename" file="${dist.jar}" suffix=".jar"/>
+ <length file="${dist.jar}" property="dist.jar.size" />
+ <local name="vmargs-token"/>
+ <condition property="vmargs-token" value="java-vm-args="${run.jvmargs}" " else="">
+ <isset property="vmargs-available"/>
+ </condition>
+ <local name="applet-params-token"/>
+ <local name="application-args-token"/>
+ <echo message="JavaScript: deploy-deploy-swing 1" level="verbose"/>
+ <script language="javascript">
+ <![CDATA[
+ var JFXPAR = "javafx.param";
+ var JFXPARN = "name";
+ var JFXPARV = "value";
+
+ var params = "";
+ var args = "";
+ var keys = project.getProperties().keys();
+ while(keys.hasMoreElements()) {
+ var pn = keys.nextElement();
+ if(pn.substr(0,JFXPAR.length) == JFXPAR && pn.indexOf(JFXPARN) == (pn.length()-JFXPARN.length)) {
+ var propn = project.getProperty(pn);
+ if(propn != null && propn.length() > 0) {
+ var pv = pn.substr(0,pn.indexOf(JFXPARN)) + JFXPARV;
+ var propv = project.getProperty(pv);
+ if(propv != null && propv.length() > 0) {
+ params += "\n <param name=\"" + propn + "\" value=\"" + propv + "\"/>";
+ args += "\n <argument>" + propn + "=" + propv + "</argument>";
+ } else {
+ params += "\n <param name=\"" + propn + "\" value=\"\"/>";
+ args += "\n <argument>" + propn + "</argument>";
+ }
+ }
+ }
+ }
+ project.setProperty("applet-params-token", params);
+ project.setProperty("application-args-token", args);
+ ]]>
+ </script>
+ <local name="application.desc.processed"/>
+ <condition property="application.desc.processed" value="${application.desc}" else="Swing applet embedding JavaFX components.">
+ <isset property="application.desc"/>
+ </condition>
+ <filterchain id="jnlp.template.filter">
+ <replacetokens>
+ <token key="NAME" value="${dist.filename}"/>
+ <token key="MAINCLASS" value="${main.class}"/>
+ <token key="FILESIZE" value="${dist.jar.size}"/>
+ <token key="VENDOR" value="${application.vendor}"/>
+ <token key="TITLE" value="${application.title}"/>
+ <token key="DESCRIPTION" value="${application.desc.processed}"/>
+ <token key="WIDTH" value="${javafx.run.width}"/>
+ <token key="HEIGHT" value="${javafx.run.height}"/>
+ <token key="PERMISSIONS" value="${permissions-elevated-token}"/>
+ <token key="OFFLINE" value="${offline-allowed-token}"/>
+ <token key="UPDATEMODE" value="${update-mode-background-token}"/>
+ <token key="ICON" value="${icon-token}"/>
+ <token key="VMARGS" value="${vmargs-token}"/>
+ <token key="PARAMETERS" value="${applet-params-token}"/>
+ <token key="ARGUMENTS" value="${application-args-token}"/>
+ </replacetokens>
+ </filterchain>
+ <copy file="${basedir}${file.separator}nbproject${file.separator}templates${file.separator}FXSwingTemplateApplication.jnlp"
+ tofile="${dist.dir}${file.separator}${dist.filename}_application.jnlp" >
+ <filterchain refid="jnlp.template.filter"/>
+ </copy>
+ <copy file="${basedir}${file.separator}nbproject${file.separator}templates${file.separator}FXSwingTemplateApplet.jnlp"
+ tofile="${dist.dir}${file.separator}${dist.filename}_applet.jnlp" >
+ <filterchain refid="jnlp.template.filter"/>
+ </copy>
+ <copy file="${basedir}${file.separator}nbproject${file.separator}templates${file.separator}FXSwingTemplate.html"
+ tofile="${dist.dir}${file.separator}${dist.filename}.html" >
+ <filterchain refid="jnlp.template.filter"/>
+ </copy>
+ <echo message="JavaScript: deploy-deploy-swing 2" level="verbose"/>
+ <script language="javascript">
+ <![CDATA[
+ var PREF = "file:";
+ var doCopyIcon = project.getProperty("local-icon-filename-available");
+ if(doCopyIcon != null) {
+ var iconProp = project.getProperty("javafx.deploy.icon");
+ if(iconProp.indexOf(PREF) == 0) {
+ iconProp = iconProp.slice(PREF.length);
+ }
+ while(iconProp.charAt(0) == "/") {
+ iconProp = iconProp.slice(1);
+ }
+ var S = java.io.File.separator;
+ var baseDir = project.getProperty("basedir");
+ var distDir = project.getProperty("dist.dir");
+ var copyTask = project.createTask("copy");
+ var source = new java.io.File(iconProp);
+ var target = new java.io.File(baseDir + S + distDir);
+ copyTask.setFile(source);
+ copyTask.setTodir(target);
+ copyTask.setFlatten(true);
+ copyTask.setFailOnError(false);
+ copyTask.perform();
+ }
+ var doCopyHTMLFrom = project.getProperty("html-template-available");
+ var doCopyHTMLTo = project.getProperty("html-template-processed-available");
+ if(doCopyHTMLFrom != null && doCopyHTMLTo != null) {
+ var htmlFrom = project.getProperty("javafx.run.htmltemplate");
+ if(htmlFrom.indexOf(PREF) == 0) {
+ htmlFrom = htmlFrom.slice(PREF.length);
+ }
+ while(htmlFrom.charAt(0) == "/") {
+ htmlFrom = htmlFrom.slice(1);
+ }
+ var htmlTo = project.getProperty("javafx.run.htmltemplate.processed");
+ if(htmlTo.indexOf(PREF) == 0) {
+ htmlTo = htmlTo.slice(PREF.length);
+ }
+ while(htmlTo.charAt(0) == "/") {
+ htmlTo = htmlTo.slice(1);
+ }
+ var copyTask = project.createTask("copy");
+ var source = new java.io.File(htmlFrom);
+ var target = new java.io.File(htmlTo);
+ copyTask.setFile(source);
+ copyTask.setTofile(target);
+ copyTask.setFailOnError(false);
+ copyTask.perform();
+ }
+ ]]>
+ </script>
+ <antcall target="-post-jfx-deploy"/>
+ </sequential>
+ </macrodef>
+
+
+ <!-- Fallback Project Deployment Macros To Support At Least Partially JDKs Without JavaScript Support -->
+
+ <macrodef name="fallback-deploy-application-def">
+ <sequential>
+ <echo message="Warning: Parameters (if any) not passed to <fx:application> in fallback build mode due to JDK missing JavaScript support."/>
+ <fx:application id="fxApp"
+ name="${application.title}"
+ mainClass="${javafx.main.class}"
+ fallbackClass="${javafx.fallback.class}">
+ <!-- PARAMETERS NOT PASSED IN FALLBACK -->
+ </fx:application>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="fallback-deploy-application-def-preloader">
+ <sequential>
+ <echo message="Warning: Parameters (if any) not passed to <fx:application> in fallback build mode due to JDK missing JavaScript support."/>
+ <fx:application id="fxApp"
+ name="${application.title}"
+ mainClass="${javafx.main.class}"
+ preloaderClass="${javafx.preloader.class}"
+ fallbackClass="${javafx.fallback.class}">
+ <!-- PARAMETERS NOT PASSED IN FALLBACK -->
+ </fx:application>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="fallback-deploy-application-def-swing">
+ <sequential>
+ <echo message="Warning: Parameters (if any) not passed to <fx:application> in fallback build mode due to JDK missing JavaScript support."/>
+ <fx:application id="fxApp"
+ name="${application.title}"
+ mainClass="${main.class}"
+ fallbackClass="${javafx.fallback.class}"
+ toolkit="swing">
+ <!-- PARAMETERS NOT PASSED IN FALLBACK -->
+ </fx:application>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="fallback-deploy-resources">
+ <sequential>
+ <fx:resources id="appRes">
+ <fx:fileset requiredFor="startup" dir="${jfx.deployment.dir}">
+ <include name="${jfx.deployment.jar}"/>
+ <include name="lib${file.separator}*.jar"/>
+ <exclude name="lib${file.separator}${jfx.deployment.jar}"/>
+ </fx:fileset>
+ </fx:resources>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="fallback-deploy-resources-preloader">
+ <sequential>
+ <fx:resources id="appRes">
+ <fx:fileset requiredFor="preloader" dir="${jfx.deployment.dir}">
+ <include name="lib${file.separator}${javafx.preloader.jar.filename}"/>
+ </fx:fileset>
+ <fx:fileset requiredFor="startup" dir="${jfx.deployment.dir}">
+ <include name="${jfx.deployment.jar}"/>
+ <include name="lib${file.separator}*.jar"/>
+ <exclude name="lib${file.separator}${javafx.preloader.jar.filename}"/>
+ <exclude name="lib${file.separator}${jfx.deployment.jar}"/>
+ </fx:fileset>
+ </fx:resources>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="fallback-deploy-jar">
+ <sequential>
+ <antcall target="-pre-jfx-jar"/>
+ <fx:jar destfile="${jfx.deployment.dir}${file.separator}${jfx.deployment.jar}">
+ <fx:application refid="fxApp"/>
+ <fx:resources refid="appRes"/>
+ <fileset dir="${build.classes.dir}">
+ <exclude name="**${file.separator}*.${css-exclude-ext}"/>
+ </fileset>
+ <manifest>
+ <attribute name="Implementation-Vendor" value="${application.vendor}"/>
+ <attribute name="Implementation-Title" value="${application.title}"/>
+ <attribute name="Implementation-Version" value="1.0"/>
+ </manifest>
+ </fx:jar>
+ <antcall target="-post-jfx-jar"/>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="fallback-deploy-deploy">
+ <sequential>
+ <antcall target="-pre-jfx-deploy"/>
+ <echo message="Warning: JVM Arguments and Callbacks (if any) not passed to <fx:deploy> in fallback build mode due to JDK missing JavaScript support."/>
+ <fx:deploy width="${javafx.width}" height="${javafx.height}"
+ outdir="${jfx.deployment.dir}" embedjnlp="true" updatemode="${update-mode}"
+ outfile="${application.title}" includeDT="${javafx.deploy.includeDT}">
+ <fx:application refid="fxApp"/>
+ <fx:resources refid="appRes"/>
+ <fx:info title="${application.title}" vendor="${application.vendor}"/>
+ <fx:permissions elevated="${permissions.elevated}"/>
+ <fx:preferences shortcut="${javafx.deploy.adddesktopshortcut}" install="${javafx.deploy.installpermanently}" menu="${javafx.deploy.addstartmenushortcut}"/>
+ <!-- PLATFORM NOT PASSED IN FALLBACK -->
+ <!-- CALLBACKS NOT PASSED IN FALLBACK -->
+ </fx:deploy>
+ <antcall target="-post-jfx-deploy"/>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="fallback-deploy-deploy-template">
+ <sequential>
+ <antcall target="-pre-jfx-deploy"/>
+ <echo message="Warning: JVM Arguments and Callbacks (if any) not passed to <fx:deploy> in fallback build mode due to JDK missing JavaScript support."/>
+ <deploy-process-template/>
+ <fx:deploy width="${javafx.width}" height="${javafx.height}"
+ outdir="${jfx.deployment.dir}" embedjnlp="true" updatemode="${update-mode}"
+ outfile="${application.title}" includeDT="${javafx.deploy.includeDT}">
+ <fx:application refid="fxApp"/>
+ <fx:resources refid="appRes"/>
+ <fx:info title="${application.title}" vendor="${application.vendor}"/>
+ <fx:permissions elevated="${permissions.elevated}"/>
+ <fx:preferences shortcut="${javafx.deploy.adddesktopshortcut}" install="${javafx.deploy.installpermanently}" menu="${javafx.deploy.addstartmenushortcut}"/>
+ <fx:template file="${javafx.run.htmltemplate}" tofile="${javafx.run.htmltemplate.processed}"/>
+ <!-- PLATFORM NOT PASSED IN FALLBACK -->
+ <!-- CALLBACKS NOT PASSED IN FALLBACK -->
+ </fx:deploy>
+ <antcall target="-post-jfx-deploy"/>
+ </sequential>
+ </macrodef>
+
+
+ <!-- Project Deployment Targets -->
+
+ <target name="-check-sign" depends="-check-project,-javafx-init-keystore" if="javafx.signed.true+signjars.task.available">
+ <condition property="sign-nopreloader-notemplate">
+ <and>
+ <isset property="app-without-preloader"/>
+ <not><isset property="html-template-available"/></not>
+ <not><isset property="fx-in-swing-app-workaround"/></not>
+ </and>
+ </condition>
+ <condition property="sign-preloader-notemplate">
+ <and>
+ <isset property="app-with-preloader"/>
+ <not><isset property="html-template-available"/></not>
+ <not><isset property="fx-in-swing-app-workaround"/></not>
+ </and>
+ </condition>
+ <condition property="sign-nopreloader-template">
+ <and>
+ <isset property="app-without-preloader"/>
+ <isset property="html-template-available"/>
+ <not><isset property="fx-in-swing-app-workaround"/></not>
+ </and>
+ </condition>
+ <condition property="sign-preloader-template">
+ <and>
+ <isset property="app-with-preloader"/>
+ <isset property="html-template-available"/>
+ <not><isset property="fx-in-swing-app-workaround"/></not>
+ </and>
+ </condition>
+ <condition property="sign-nopreloader-notemplate-swing">
+ <and>
+ <isset property="app-without-preloader"/>
+ <not><isset property="html-template-available"/></not>
+ <isset property="fx-in-swing-app-workaround"/>
+ </and>
+ </condition>
+ <condition property="sign-nopreloader-template-swing">
+ <and>
+ <isset property="app-without-preloader"/>
+ <isset property="html-template-available"/>
+ <isset property="fx-in-swing-app-workaround"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-check-nosign" depends="-check-project">
+ <condition property="nosign-nopreloader-notemplate">
+ <and>
+ <isset property="app-without-preloader"/>
+ <not><isset property="html-template-available"/></not>
+ <not><isset property="javafx.signed.true"/></not>
+ <not><isset property="fx-in-swing-app-workaround"/></not>
+ </and>
+ </condition>
+ <condition property="nosign-preloader-notemplate">
+ <and>
+ <isset property="app-with-preloader"/>
+ <not><isset property="html-template-available"/></not>
+ <not><isset property="javafx.signed.true"/></not>
+ <not><isset property="fx-in-swing-app-workaround"/></not>
+ </and>
+ </condition>
+ <condition property="nosign-nopreloader-template">
+ <and>
+ <isset property="app-without-preloader"/>
+ <isset property="html-template-available"/>
+ <not><isset property="javafx.signed.true"/></not>
+ <not><isset property="fx-in-swing-app-workaround"/></not>
+ </and>
+ </condition>
+ <condition property="nosign-preloader-template">
+ <and>
+ <isset property="app-with-preloader"/>
+ <isset property="html-template-available"/>
+ <not><isset property="javafx.signed.true"/></not>
+ <not><isset property="fx-in-swing-app-workaround"/></not>
+ </and>
+ </condition>
+ <condition property="nosign-nopreloader-notemplate-swing">
+ <and>
+ <isset property="app-without-preloader"/>
+ <not><isset property="html-template-available"/></not>
+ <not><isset property="javafx.signed.true"/></not>
+ <isset property="fx-in-swing-app-workaround"/>
+ </and>
+ </condition>
+ <condition property="nosign-nopreloader-template-swing">
+ <and>
+ <isset property="app-without-preloader"/>
+ <isset property="html-template-available"/>
+ <not><isset property="javafx.signed.true"/></not>
+ <isset property="fx-in-swing-app-workaround"/>
+ </and>
+ </condition>
+ </target>
+
+
+ <!-- WITH SIGNING -->
+
+ <!-- project without preloader -->
+ <!-- no html template -->
+ <target name="-deploy-app-sign-nopreloader-notemplate" depends="-check-sign" if="sign-nopreloader-notemplate" unless="preloader-app">
+ <echo message="-deploy-app-sign-nopreloader-notemplate" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <deploy-jar/>
+ <deploy-sign/>
+ <deploy-deploy/>
+ </target>
+
+ <!-- project with preloader -->
+ <!-- no html template -->
+ <target name="-deploy-app-sign-preloader-notemplate" depends="-check-sign" if="sign-preloader-notemplate" unless="preloader-app">
+ <echo message="-deploy-app-sign-preloader-notemplate" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <deploy-jar/>
+ <deploy-sign-preloader/>
+ <deploy-deploy/>
+ </target>
+
+ <!-- project without preloader -->
+ <!-- html template -->
+ <target name="-deploy-app-sign-nopreloader-template" depends="-check-sign" if="sign-nopreloader-template" unless="preloader-app">
+ <echo message="-deploy-app-sign-nopreloader-template" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <deploy-jar/>
+ <deploy-sign/>
+ <deploy-process-template/>
+ <deploy-deploy/>
+ </target>
+
+ <!-- project with preloader -->
+ <!-- html template -->
+ <target name="-deploy-app-sign-preloader-template" depends="-check-sign" if="sign-preloader-template" unless="preloader-app">
+ <echo message="-deploy-app-sign-preloader-template" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <deploy-jar/>
+ <deploy-sign-preloader/>
+ <deploy-process-template/>
+ <deploy-deploy/>
+ </target>
+
+ <!-- project without preloader -->
+ <!-- no html template -->
+ <!-- FX in Swing app -->
+ <target name="-deploy-app-sign-nopreloader-notemplate-swing" depends="-check-sign" if="sign-nopreloader-notemplate-swing" unless="preloader-app-no-workaround">
+ <echo message="-deploy-app-sign-nopreloader-notemplate-swing" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <deploy-jar/>
+ <deploy-sign/>
+ <deploy-deploy-swing/>
+ </target>
+
+ <!-- project without preloader -->
+ <!-- html template -->
+ <!-- FX in Swing app -->
+ <target name="-deploy-app-sign-nopreloader-template-swing" depends="-check-sign" if="sign-nopreloader-template-swing" unless="preloader-app-no-workaround">
+ <echo message="-deploy-app-sign-nopreloader-template-swing" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <deploy-jar/>
+ <deploy-sign/>
+ <deploy-process-template/>
+ <deploy-deploy-swing/>
+ </target>
+
+
+ <!-- NO SIGNING -->
+
+ <!-- project without preloader -->
+ <!-- no html template -->
+ <target name="-deploy-app-nosign-nopreloader-notemplate" depends="-check-nosign" if="nosign-nopreloader-notemplate" unless="preloader-app">
+ <echo message="-deploy-app-nosign-nopreloader-notemplate" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <deploy-jar/>
+ <deploy-deploy/>
+ </target>
+
+ <!-- project with preloader -->
+ <!-- no html template -->
+ <target name="-deploy-app-nosign-preloader-notemplate" depends="-check-nosign" if="nosign-preloader-notemplate" unless="preloader-app">
+ <echo message="-deploy-app-nosign-preloader-notemplate" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <deploy-jar/>
+ <deploy-deploy/>
+ </target>
+
+ <!-- project without preloader -->
+ <!-- html template -->
+ <target name="-deploy-app-nosign-nopreloader-template" depends="-check-nosign" if="nosign-nopreloader-template" unless="preloader-app">
+ <echo message="-deploy-app-nosign-nopreloader-template" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <deploy-jar/>
+ <deploy-process-template/>
+ <deploy-deploy/>
+ </target>
+
+ <!-- project with preloader -->
+ <!-- html template -->
+ <target name="-deploy-app-nosign-preloader-template" depends="-check-nosign" if="nosign-preloader-template" unless="preloader-app">
+ <echo message="-deploy-app-nosign-preloader-template" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <deploy-jar/>
+ <deploy-process-template/>
+ <deploy-deploy/>
+ </target>
+
+ <!-- project without preloader -->
+ <!-- no html template -->
+ <!-- FX in Swing app -->
+ <target name="-deploy-app-nosign-nopreloader-notemplate-swing" depends="-check-nosign" if="nosign-nopreloader-notemplate-swing" unless="preloader-app-no-workaround">
+ <echo message="-deploy-app-nosign-nopreloader-notemplate-swing" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <deploy-jar/>
+ <deploy-deploy-swing/>
+ </target>
+
+ <!-- project without preloader -->
+ <!-- html template -->
+ <!-- FX in Swing app -->
+ <target name="-deploy-app-nosign-nopreloader-template-swing" depends="-check-nosign" if="nosign-nopreloader-template-swing" unless="preloader-app-no-workaround">
+ <echo message="-deploy-app-nosign-nopreloader-template-swing" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <deploy-jar/>
+ <deploy-process-template/>
+ <deploy-deploy-swing/>
+ </target>
+
+
+ <!-- FALLBACK (NO JAVASCRIPT) TARGETS WITH SIGNING -->
+
+ <target name="-check-fallback-sign-deploy-swing-possible" depends="-check-sign">
+ <local name="fail-deploy-swing-possible"/>
+ <condition property="fail-deploy-swing-possible">
+ <and>
+ <or>
+ <isset property="sign-nopreloader-notemplate-swing"/>
+ <isset property="sign-nopreloader-template-swing"/>
+ </or>
+ <not><isset property="have-fx-ant-api-1.2"/></not>
+ </and>
+ </condition>
+ <fail message="Error: JavaFX SDK version 2.2 or newer is needed to deploy FX-in-Swing on JDK without JavaScript support."
+ if="fail-deploy-swing-possible"/>
+ </target>
+
+ <!-- FALLBACK project without preloader -->
+ <!-- FALLBACK no html template -->
+ <target name="-fallback-deploy-app-sign-nopreloader-notemplate" depends="-check-sign" if="sign-nopreloader-notemplate" unless="preloader-app">
+ <echo message="-fallback-deploy-app-sign-nopreloader-notemplate" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <fallback-deploy-application-def/>
+ <fallback-deploy-resources/>
+ <fallback-deploy-jar/>
+ <deploy-sign/>
+ <fallback-deploy-deploy/>
+ </target>
+
+ <!-- FALLBACK project with preloader -->
+ <!-- FALLBACK no html template -->
+ <target name="-fallback-deploy-app-sign-preloader-notemplate" depends="-check-sign" if="sign-preloader-notemplate" unless="preloader-app">
+ <echo message="-fallback-deploy-app-sign-preloader-notemplate" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <fallback-deploy-application-def-preloader/>
+ <fallback-deploy-resources-preloader/>
+ <fallback-deploy-jar/>
+ <deploy-sign-preloader/>
+ <fallback-deploy-deploy/>
+ </target>
+
+ <!-- FALLBACK project without preloader -->
+ <!-- FALLBACK html template -->
+ <target name="-fallback-deploy-app-sign-nopreloader-template" depends="-check-sign" if="sign-nopreloader-template" unless="preloader-app">
+ <echo message="-fallback-deploy-app-sign-nopreloader-template" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <fallback-deploy-application-def/>
+ <fallback-deploy-resources/>
+ <fallback-deploy-jar/>
+ <deploy-sign/>
+ <fallback-deploy-deploy-template/>
+ </target>
+
+ <!-- FALLBACK project with preloader -->
+ <!-- FALLBACK html template -->
+ <target name="-fallback-deploy-app-sign-preloader-template" depends="-check-sign" if="sign-preloader-template" unless="preloader-app">
+ <echo message="-fallback-deploy-app-sign-preloader-template" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <fallback-deploy-application-def-preloader/>
+ <fallback-deploy-resources-preloader/>
+ <fallback-deploy-jar/>
+ <deploy-sign-preloader/>
+ <fallback-deploy-deploy-template/>
+ </target>
+
+ <!-- FALLBACK project without preloader -->
+ <!-- FALLBACK no html template -->
+ <!-- FALLBACK FX in Swing app -->
+ <target name="-fallback-deploy-app-sign-nopreloader-notemplate-swing" depends="-check-fallback-sign-deploy-swing-possible" if="sign-nopreloader-notemplate-swing" unless="preloader-app-no-workaround">
+ <echo message="-fallback-deploy-app-sign-nopreloader-notemplate-swing" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <fallback-deploy-application-def-swing/>
+ <fallback-deploy-resources/>
+ <fallback-deploy-jar/>
+ <deploy-sign/>
+ <fallback-deploy-deploy/>
+ </target>
+
+ <!-- FALLBACK project without preloader -->
+ <!-- FALLBACK html template -->
+ <!-- FALLBACK FX in Swing app -->
+ <target name="-fallback-deploy-app-sign-nopreloader-template-swing" depends="-check-fallback-sign-deploy-swing-possible" if="sign-nopreloader-template-swing" unless="preloader-app-no-workaround">
+ <echo message="-fallback-deploy-app-sign-nopreloader-template-swing" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <fallback-deploy-application-def-swing/>
+ <fallback-deploy-resources/>
+ <fallback-deploy-jar/>
+ <deploy-sign/>
+ <fallback-deploy-deploy-template/>
+ </target>
+
+
+ <!-- FALLBACK (NO JAVASCRIPT) TARGETS NO SIGNING -->
+
+ <target name="-check-fallback-nosign-deploy-swing-possible" depends="-check-nosign">
+ <local name="fail-deploy-swing-possible"/>
+ <condition property="fail-deploy-swing-possible">
+ <and>
+ <or>
+ <isset property="nosign-nopreloader-notemplate-swing"/>
+ <isset property="nosign-nopreloader-template-swing"/>
+ </or>
+ <not><isset property="have-fx-ant-api-1.2"/></not>
+ </and>
+ </condition>
+ <fail message="Error: JavaFX SDK version 2.2 or newer is needed to deploy FX-in-Swing on JDK without JavaScript support."
+ if="fail-deploy-swing-possible"/>
+ </target>
+
+ <!-- FALLBACK project without preloader -->
+ <!-- FALLBACK no html template -->
+ <target name="-fallback-deploy-app-nosign-nopreloader-notemplate" depends="-check-nosign" if="nosign-nopreloader-notemplate" unless="preloader-app">
+ <echo message="-fallback-deploy-app-nosign-nopreloader-notemplate" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <fallback-deploy-application-def/>
+ <fallback-deploy-resources/>
+ <fallback-deploy-jar/>
+ <fallback-deploy-deploy/>
+ </target>
+
+ <!-- FALLBACK project with preloader -->
+ <!-- FALLBACK no html template -->
+ <target name="-fallback-deploy-app-nosign-preloader-notemplate" depends="-check-nosign" if="nosign-preloader-notemplate" unless="preloader-app">
+ <echo message="-fallback-deploy-app-nosign-preloader-notemplate" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <fallback-deploy-application-def-preloader/>
+ <fallback-deploy-resources-preloader/>
+ <fallback-deploy-jar/>
+ <fallback-deploy-deploy/>
+ </target>
+
+ <!-- FALLBACK project without preloader -->
+ <!-- FALLBACK html template -->
+ <target name="-fallback-deploy-app-nosign-nopreloader-template" depends="-check-nosign" if="nosign-nopreloader-template" unless="preloader-app">
+ <echo message="-fallback-deploy-app-nosign-nopreloader-template" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <fallback-deploy-application-def/>
+ <fallback-deploy-resources/>
+ <fallback-deploy-jar/>
+ <fallback-deploy-deploy-template/>
+ </target>
+
+ <!-- FALLBACK project with preloader -->
+ <!-- FALLBACK html template -->
+ <target name="-fallback-deploy-app-nosign-preloader-template" depends="-check-nosign" if="nosign-preloader-template" unless="preloader-app">
+ <echo message="-fallback-deploy-app-nosign-preloader-template" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <fallback-deploy-application-def-preloader/>
+ <fallback-deploy-resources-preloader/>
+ <fallback-deploy-jar/>
+ <fallback-deploy-deploy-template/>
+ </target>
+
+ <!-- FALLBACK project without preloader -->
+ <!-- FALLBACK no html template -->
+ <!-- FALLBACK FX in Swing app -->
+ <target name="-fallback-deploy-app-nosign-nopreloader-notemplate-swing" depends="-check-fallback-nosign-deploy-swing-possible" if="nosign-nopreloader-notemplate-swing" unless="preloader-app-no-workaround">
+ <echo message="-fallback-deploy-app-nosign-nopreloader-notemplate-swing" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <fallback-deploy-application-def-swing/>
+ <fallback-deploy-resources/>
+ <fallback-deploy-jar/>
+ <fallback-deploy-deploy/>
+ </target>
+
+ <!-- FALLBACK project without preloader -->
+ <!-- FALLBACK html template -->
+ <!-- FALLBACK FX in Swing app -->
+ <target name="-fallback-deploy-app-nosign-nopreloader-template-swing" depends="-check-fallback-nosign-deploy-swing-possible" if="nosign-nopreloader-template-swing" unless="preloader-app-no-workaround">
+ <echo message="-fallback-deploy-app-nosign-nopreloader-template-swing" level="verbose"/>
+ <deploy-defines/>
+ <deploy-preprocess/>
+ <fallback-deploy-application-def-swing/>
+ <fallback-deploy-resources/>
+ <fallback-deploy-jar/>
+ <fallback-deploy-deploy-template/>
+ </target>
+
+
+ <!-- Project Build Targets -->
+
+ <target name="jfx-build" depends="-jfx-do-compile, -jfx-do-jar, -jfx-do-post-jar"/>
+ <target name="jfx-build-noscript" depends="-set-fallback-no-javascript, -jfx-do-compile, -jfx-do-jar, -jfx-do-post-jar"/>
+
+ <target name="jfx-rebuild" depends="clean, -jfx-do-compile, -jfx-do-jar, -jfx-do-post-jar"/>
+ <target name="jfx-rebuild-noscript" depends="-set-fallback-no-javascript, clean, -jfx-do-compile, -jfx-do-jar, -jfx-do-post-jar"/>
+
+ <target name="jfx-build-native" depends="-set-do-build-native-package, -check-ant-jre-supports-native-packaging, -check-native-packager-external-tools, jfx-rebuild"/>
+ <target name="jfx-build-native-noscript" depends="-set-do-build-native-package, -check-ant-jre-supports-native-packaging, -check-native-packager-external-tools, jfx-rebuild-noscript"/>
+
+ <target name="-check-do-jar">
+ <condition property="do-jar-false">
+ <and>
+ <isset property="do.jar"/>
+ <equals arg1="${do.jar}" arg2="false"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-set-fallback-no-javascript">
+ <property name="fallback.no.javascript" value="true"/>
+ <echo message="Warning: Using fallback build infrastructure due to default JDK missing JavaScript support."/>
+ </target>
+ <target name="-jfx-do-compile" depends="-check-do-jar" if="do-jar-false">
+ <antcall target="compile"/>
+ </target>
+ <target name="-jfx-do-jar" depends="-check-do-jar" unless="do-jar-false">
+ <antcall target="jar"/>
+ </target>
+ <target name="-jfx-do-post-jar" depends="-init-check,-check-project" if="preloader-app">
+ <!-- Preloaders are created using SE copylibs task that creates readme file relevant for SE only -->
+ <delete file="${basedir}${file.separator}${dist.dir}${file.separator}README.TXT"/>
+ </target>
+
+ <target name="-set-do-build-native-package">
+ <property name="do.build.native.package" value="true"/>
+ <echo message="do.build.native.package = ${do.build.native.package}" level="verbose"/>
+ </target>
+ <target name="-check-ant-jre-supports-native-packaging" depends="-check-ant-jre-version">
+ <fail message="Error:${line.separator}JavaFX native packager requires NetBeans to run on JDK 1.7u6 or later !" if="have-ant-jre-pre7u6"/>
+ </target>
+
+ <target name="-call-pre-jfx-native" if="do.build.native.package">
+ <antcall target="-pre-jfx-native"/>
+ </target>
+ <target name="-call-post-jfx-native" if="do.build.native.package">
+ <antcall target="-post-jfx-native"/>
+ </target>
+
+ <target name="-check-native-bundling-type" depends="-check-operating-system" if="do.build.native.package">
+ <condition property="need.Inno.presence">
+ <and>
+ <isset property="running.on.windows"/>
+ <isset property="javafx.native.bundling.type"/>
+ <or>
+ <equals arg1="${javafx.native.bundling.type}" arg2="all" casesensitive="false"/>
+ <equals arg1="${javafx.native.bundling.type}" arg2="installer" casesensitive="false"/>
+ </or>
+ </and>
+ </condition>
+ <condition property="need.WiX.presence">
+ <and>
+ <isset property="running.on.windows"/>
+ <isset property="javafx.native.bundling.type"/>
+ <or>
+ <equals arg1="${javafx.native.bundling.type}" arg2="all" casesensitive="false"/>
+ <equals arg1="${javafx.native.bundling.type}" arg2="installer" casesensitive="false"/>
+ </or>
+ </and>
+ </condition>
+ <echo message="need.Inno.presence:${need.Inno.presence}" level="verbose"/>
+ <echo message="need.WiX.presence:${need.WiX.presence}" level="verbose"/>
+ </target>
+ <target name="-check-Inno-presence" depends="-check-native-bundling-type" if="need.Inno.presence">
+ <local name="exec-output"/>
+ <local name="exec-error"/>
+ <local name="exec-result"/>
+ <exec executable="iscc" outputproperty="exec-output" failifexecutionfails="false" errorproperty="exec-error" resultproperty="exec-result"/>
+ <echo message="exec-output:${exec-output}" level="verbose"/>
+ <echo message="exec-error:${exec-error}" level="verbose"/>
+ <echo message="exec-result:${exec-result}" level="verbose"/>
+ <condition property="missing.Inno">
+ <not><and>
+ <contains string="${exec-output}" substring="Inno Setup"/>
+ <not><contains string="${exec-output}" substring="Inno Setup 1"/></not>
+ <not><contains string="${exec-output}" substring="Inno Setup 2"/></not>
+ <not><contains string="${exec-output}" substring="Inno Setup 3"/></not>
+ <not><contains string="${exec-output}" substring="Inno Setup 4"/></not>
+ </and></not>
+ </condition>
+ </target>
+ <target name="-check-WiX-presence" depends="-check-native-bundling-type" if="need.WiX.presence">
+ <local name="exec-output"/>
+ <local name="exec-error"/>
+ <local name="exec-result"/>
+ <exec executable="candle" outputproperty="exec-output" failifexecutionfails="false" errorproperty="exec-error" resultproperty="exec-result">
+ <arg value="-?"/>
+ </exec>
+ <echo message="exec-output:${exec-output}" level="verbose"/>
+ <echo message="exec-error:${exec-error}" level="verbose"/>
+ <echo message="exec-result:${exec-result}" level="verbose"/>
+ <condition property="missing.WiX">
+ <not><and>
+ <contains string="${exec-output}" substring="Windows Installer Xml Compiler version"/>
+ <not><contains string="${exec-output}" substring="Windows Installer Xml Compiler version 1"/></not>
+ <not><contains string="${exec-output}" substring="Windows Installer Xml Compiler version 2"/></not>
+ </and></not>
+ </condition>
+ </target>
+ <target name="-check-native-packager-external-tools" depends="-check-Inno-presence, -check-WiX-presence">
+ <property name="missing.Inno.message" value="JavaFX native packager requires external Inno Setup 5+ tools installed and included on PATH. See http://www.jrsoftware.org/"/>
+ <property name="missing.WiX.message" value="JavaFX native packager requires external WiX 3.0+ tools installed and included on PATH. See http://wix.sourceforge.net/"/>
+ <condition property="missing.Inno.WiX">
+ <and>
+ <isset property="missing.Inno"/>
+ <isset property="missing.WiX"/>
+ </and>
+ </condition>
+ <fail message="Error:${line.separator}${missing.Inno.message}${line.separator}${missing.WiX.message}" if="missing.Inno.WiX"/>
+ <fail message="Error:${line.separator}${missing.Inno.message}" if="missing.Inno"/>
+ <fail message="Error:${line.separator}${missing.WiX.message}" if="missing.WiX"/>
+ </target>
+
+ <!-- Project Run Support -->
+
+ <target name="-warn-of-preloader" depends="-check-project" if="preloader-app-no-workaround">
+ <fail message="Error:${line.separator}JavaFX 2 Preloader Project can not be executed directly.${line.separator}Please execute instead a JavaFX Application that uses the Preloader."/>
+ </target>
+
+ <target name="-mark-project-state-running">
+ <property name="project.state.running" value="true"/>
+ <echo message="project.state.running = ${project.state.running}" level="verbose"/>
+ </target>
+ <target name="-mark-project-state-debugging">
+ <property name="project.state.debugging" value="true"/>
+ <echo message="project.state.debugging = ${project.state.debugging}" level="verbose"/>
+ </target>
+ <target name="-mark-project-state-profiling">
+ <property name="project.state.profiling" value="true"/>
+ <echo message="project.state.profiling = ${project.state.profiling}" level="verbose"/>
+ </target>
+ <target name="-mark-project-needs-jnlp">
+ <property name="project.needs.jnlp" value="true"/>
+ <echo message="project.needs.jnlp = ${project.needs.jnlp}" level="verbose"/>
+ </target>
+
+ <!-- set property javafx.disable.concurrent.runs=true to disable runs from temporary directory -->
+ <target name="-check-concurrent-runs">
+ <condition property="disable-concurrent-runs">
+ <and>
+ <isset property="javafx.disable.concurrent.runs"/>
+ <equals arg1="${javafx.disable.concurrent.runs}" arg2="true" trim="true"/>
+ </and>
+ </condition>
+ <condition property="temp.run.jar" value="${jfx.deployment.dir}${file.separator}${jfx.deployment.jar}">
+ <isset property="disable-concurrent-runs"/>
+ </condition>
+ <condition property="temp.run.jnlp" value="${jfx.deployment.jnlp}">
+ <isset property="disable-concurrent-runs"/>
+ </condition>
+ <condition property="temp.run.html" value="${jfx.deployment.html}">
+ <isset property="disable-concurrent-runs"/>
+ </condition>
+ </target>
+ <target name="-create-temp-run-dir" depends="-check-concurrent-runs" unless="disable-concurrent-runs">
+ <echo message="Creating temp run dir" level="verbose"/>
+ <tempfile property="temp.run.dir" destDir="${basedir}${file.separator}${dist.dir}${file.separator}" prefix="run"/>
+ <echo message="temp.run.dir = ${temp.run.dir}" level="verbose"/>
+ <copy todir="${temp.run.dir}" includeemptydirs="true" overwrite="true">
+ <fileset dir="${basedir}${file.separator}${dist.dir}">
+ <exclude name="**${file.separator}bundles${file.separator}**"/>
+ <exclude name="**${file.separator}run*${file.separator}**"/>
+ </fileset>
+ </copy>
+ <property name="temp.run.jar" value="${temp.run.dir}${file.separator}${jfx.deployment.jar}"/>
+ <basename property="jfx.deployment.base" file="${jfx.deployment.jar}" suffix=".jar"/>
+ <property name="temp.run.jnlp" value="${temp.run.dir}${file.separator}${jfx.deployment.base}.jnlp"/>
+ <property name="temp.run.html" value="${temp.run.dir}${file.separator}${jfx.deployment.base}.html"/>
+ </target>
+ <target name="-remove-temp-run-dir" if="temp.run.dir">
+ <echo message="Removing temp run dir" level="verbose"/>
+ <delete dir="${temp.run.dir}" quiet="true" failonerror="false"/>
+ </target>
+ <target depends="init,compile,jar,-create-temp-run-dir" description="Run JavaFX project standalone." name="jfx-project-run">
+ <echo message="Executing ${main.class} from ${temp.run.jar} using platform ${platform.java}"/>
+ <property name="run.jvmargs" value=""/>
+ <property name="run.jvmargs.ide" value=""/>
+ <java classname="${main.class}" dir="${work.dir}" fork="true" jvm="${platform.java}">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+ <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ <classpath>
+ <path path="${temp.run.jar}:${javac.classpath}"/>
+ </classpath>
+ <arg line="${application.args}"/>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ </java>
+ <antcall target="-remove-temp-run-dir"/>
+ </target>
+
+
+ <!-- Running/Debugging/Profiling Standalone -->
+
+ <target name="jfxsa-run" depends="-mark-project-state-running,-clean-if-config-changed,-check-jfx-runtime,-warn-of-preloader,jfx-project-run"/>
+ <target name="jfxsa-run-noscript" depends="-set-fallback-no-javascript, jfxsa-run"/>
+
+ <target name="jfxsa-debug" depends="-mark-project-state-debugging,-clean-if-config-changed,jar,-check-jfx-runtime,-warn-of-preloader,debug"/>
+ <target name="jfxsa-debug-noscript" depends="-set-fallback-no-javascript, jfxsa-debug"/>
+
+ <target name="jfxsa-profile" depends="-mark-project-state-profiling,-check-jfx-runtime,-warn-of-preloader,profile"/>
+ <target name="jfxsa-profile-noscript" depends="-set-fallback-no-javascript, jfxsa-profile"/>
+
+ <target name="-check-clean-if-config-changed" depends="-init-project">
+ <deploy-defines/>
+ <uptodate property="jfx.deployment.jar.newer.than.nbproject" targetfile="${jfx.deployment.dir}${file.separator}${jfx.deployment.jar}" >
+ <srcfiles dir="${basedir}${file.separator}nbproject" includes="**${file.separator}*"/>
+ </uptodate>
+ <echo message="jfx.deployment.jar.newer.than.nbproject = ${jfx.deployment.jar.newer.than.nbproject}" level="verbose"/>
+ <available file="${jfx.deployment.dir}${file.separator}${jfx.deployment.jar}" type="file" property="jfx.deployment.jar.exists"/>
+ <condition property="request.clean.due.to.config.change">
+ <and>
+ <isset property="jfx.deployment.jar.exists"/>
+ <not><isset property="jfx.deployment.jar.newer.than.nbproject"/></not>
+ </and>
+ </condition>
+ </target>
+ <target name="-clean-if-config-changed" depends="-check-clean-if-config-changed" if="request.clean.due.to.config.change">
+ <echo message="Config change detected. Invoking clean." level="verbose"/>
+ <antcall target="clean"/>
+ </target>
+
+
+ <!-- Shared Debugging init -->
+
+ <target name="-init-debug-args">
+ <property name="version-output" value="java version "${ant.java.version}"/>
+ <condition property="have-jdk-older-than-1.4">
+ <or>
+ <contains string="${version-output}" substring="java version "1.0"/>
+ <contains string="${version-output}" substring="java version "1.1"/>
+ <contains string="${version-output}" substring="java version "1.2"/>
+ <contains string="${version-output}" substring="java version "1.3"/>
+ </or>
+ </condition>
+ <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
+ <istrue value="${have-jdk-older-than-1.4}"/>
+ </condition>
+ <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
+ <os family="windows"/>
+ </condition>
+ <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
+ <isset property="debug.transport"/>
+ </condition>
+ </target>
+
+
+ <!-- Running/Debugging/Profiling as WebStart -->
+
+ <target name="-check-jnlp-file-fx" depends="-swing-api-check" unless="fx-in-swing-app-workaround">
+ <basename property="jfx.deployment.base" file="${jfx.deployment.jar}" suffix=".jar"/>
+ <property name="jfx.deployment.jnlp" location="${jfx.deployment.dir}${file.separator}${jfx.deployment.base}.jnlp"/>
+ </target>
+ <target name="-check-jnlp-file-swing" depends="-swing-api-check" if="fx-in-swing-app-workaround">
+ <basename property="jfx.deployment.base" file="${jfx.deployment.jar}" suffix=".jar"/>
+ <property name="jfx.deployment.jnlp" location="${jfx.deployment.dir}${file.separator}${jfx.deployment.base}_application.jnlp"/>
+ </target>
+ <target name="-check-jnlp-file" depends="-check-jnlp-file-fx,-check-jnlp-file-swing">
+ <condition property="jnlp-file-exists">
+ <available file="${jfx.deployment.jnlp}"/>
+ </condition>
+ <condition property="jnlp-file-exists+netbeans.home">
+ <and>
+ <isset property="jnlp-file-exists"/>
+ <isset property="netbeans.home"/>
+ </and>
+ </condition>
+ </target>
+
+ <target name="-resolve-jnlp-file" depends="-check-jnlp-file" unless="jnlp-file-exists">
+ <antcall target="jfx-deployment"/>
+ <antcall target="-check-jnlp-file"/>
+ </target>
+
+ <!-- set property javafx.enable.concurrent.external.runs=true to enable multiple runs of the same WebStart or Run-in-Browser project -->
+ <target name="-check-concurrent-jnlp-runs" depends="-resolve-jnlp-file">
+ <condition property="disable-concurrent-runs">
+ <not>
+ <and>
+ <isset property="javafx.enable.concurrent.external.runs"/>
+ <equals arg1="${javafx.enable.concurrent.external.runs}" arg2="true" trim="true"/>
+ </and>
+ </not>
+ </condition>
+ <condition property="temp.run.jnlp" value="${jfx.deployment.jnlp}">
+ <isset property="disable-concurrent-runs"/>
+ </condition>
+ </target>
+ <target name="-warn-concurrent-jnlp-runs" unless="disable-concurrent-runs">
+ <echo message="Note: Concurrent Run as WebStart enabled.${line.separator}Temporary directory ${temp.run.dir}${line.separator}will remain unused when WebStart execution has finished. Use project Clean to delete unused directories."/>
+ </target>
+
+ <target name="jfxws-run" if="jnlp-file-exists" depends="-mark-project-state-running,-clean-if-config-changed,-mark-project-needs-jnlp,-check-jdk-7u4or5-mac,jar,
+ -check-jfx-webstart,-resolve-jnlp-file,-check-jfx-runtime,-check-concurrent-jnlp-runs,-create-temp-run-dir"
+ description="Start JavaFX javaws execution">
+ <echo message="Executing ${temp.run.jnlp} using ${active.webstart.executable}"/>
+ <exec executable="${active.webstart.executable}">
+ <arg file="${temp.run.jnlp}"/>
+ </exec>
+ <antcall target="-warn-concurrent-jnlp-runs"/>
+ </target>
+
+ <target name="jfxws-debug" if="jnlp-file-exists+netbeans.home" depends="-mark-project-state-debugging,-clean-if-config-changed,-mark-project-needs-jnlp,
+ -check-jdk-7u4or5-mac,jar,-check-jfx-webstart,-resolve-jnlp-file,-check-jfx-runtime,
+ -debug-start-debugger,-debug-javaws-debuggee" description="Debug JavaFX javaws project in IDE"/>
+
+ <target name="-debug-javaws-debuggee" depends="-init-debug-args">
+ <echo message="Executing ${jfx.deployment.jnlp} in debug mode using ${active.webstart.executable}"/>
+ <exec executable="${active.webstart.executable}">
+ <env key="JAVAWS_VM_ARGS" value="${debug-args-line} -Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <arg value="-wait"/>
+ <arg file="${jfx.deployment.jnlp}"/>
+ </exec>
+ </target>
+
+ <target name="-profile-check-1">
+ <property name="run.jvmargs.ide" value=""/>
+ <condition property="profiler.configured">
+ <or>
+ <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-agentpath:"/>
+ <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-javaagent:"/>
+ </or>
+ </condition>
+ </target>
+
+ <target if="jnlp-file-exists+netbeans.home" name="-profile-check-jnlp">
+ <antcall target="-profile-check-1"/>
+ </target>
+
+ <target name="-do-jfxws-profile" depends="-mark-project-state-profiling,-mark-project-needs-jnlp,
+ -check-jdk-7u4or5-mac,jar,-check-jfx-webstart,-resolve-jnlp-file,-check-jfx-runtime">
+ <echo message="Executing ${jfx.deployment.jnlp} in profile mode using ${active.webstart.executable}"/>
+ <property name="run.jvmargs.ide" value=""/>
+ <exec executable="${active.webstart.executable}">
+ <env key="JAVAWS_VM_ARGS" value="${run.jvmargs.ide}"/>
+ <arg value="-wait"/>
+ <arg file="${jfx.deployment.jnlp}"/>
+ </exec>
+ </target>
+
+ <target name="jfxws-profile" if="profiler.configured"
+ depends="-profile-check-1"
+ description="Profile JavaFX javaws project in IDE">
+ <startprofiler/>
+ <antcall target="-do-jfxws-profile"/>
+ </target>
+
+ <target name="jfxws-run-noscript" depends="-set-fallback-no-javascript, jfxws-run"/>
+
+ <target name="jfxws-debug-noscript" depends="-set-fallback-no-javascript, jfxws-debug"/>
+
+ <target name="jfxws-profile-noscript" depends="-set-fallback-no-javascript, jfxws-profile"/>
+
+
+ <!-- Running/Debugging/Profiling in Browser -->
+
+ <target name="-check-selected-browser-path" depends="-check-default-run-config">
+ <condition property="javafx.run.inbrowser.undefined">
+ <or>
+ <and>
+ <isset property="javafx.run.inbrowser"/>
+ <equals arg1="${javafx.run.inbrowser}" arg2="undefined"/>
+ </and>
+ <and>
+ <isset property="javafx.run.inbrowser.path"/>
+ <equals arg1="${javafx.run.inbrowser.path}" arg2="undefined"/>
+ </and>
+ </or>
+ </condition>
+ <condition property="javafx.run.inbrowser.path-exists">
+ <and>
+ <isset property="javafx.run.inbrowser.path"/>
+ <available file="${javafx.run.inbrowser.path}"/>
+ </and>
+ </condition>
+ <fail message="Error:${line.separator}Browser selection not recognizable from ${config} run configuration.${line.separator}Please go to Project Properties dialog, category Run, to select a valid browser." unless="javafx.run.inbrowser.path"/>
+ <fail message="Error:${line.separator}No browser defined in ${config} run configuration.${line.separator}Please verify in Tools->Options dialog that NetBeans recognizes a valid browser, then go to Project Properties dialog, category Run, to select a valid browser." if="javafx.run.inbrowser.undefined"/>
+ <fail message="Error:${line.separator}Browser ${javafx.run.inbrowser.path} referred from ${config} run configuration can not be found.${line.separator}(This can happen, e.g, when the JavaFX Project is transferred to another system.)${line.separator}Please go to Project Properties dialog, category Run, to select a valid browser." unless="javafx.run.inbrowser.path-exists"/>
+ </target>
+
+ <target name="-substitute-template-processed-html-file" depends="-check-project" if="html-template-available">
+ <deploy-process-template/>
+ </target>
+ <target name="-check-template-processed-html-file" depends="-substitute-template-processed-html-file">
+ <condition property="html-file-exists">
+ <and>
+ <isset property="html-template-available"/>
+ <available file="${javafx.run.htmltemplate.processed}"/>
+ </and>
+ </condition>
+ </target>
+
+ <target name="-set-template-processed-html-file" depends="-check-template-processed-html-file" if="html-file-exists">
+ <property name="jfx.deployment.html" location="${javafx.run.htmltemplate.processed}"/>
+ </target>
+
+ <target name="-set-html-file" depends="-set-template-processed-html-file" unless="html-file-exists">
+ <basename property="jfx.deployment.base" file="${jfx.deployment.jar}" suffix=".jar"/>
+ <property name="jfx.deployment.html" location="${jfx.deployment.dir}${file.separator}${jfx.deployment.base}.html"/>
+ <condition property="html-file-exists">
+ <available file="${jfx.deployment.html}"/>
+ </condition>
+ <condition property="html-file-exists+netbeans.home">
+ <and>
+ <isset property="html-file-exists"/>
+ <isset property="netbeans.home"/>
+ </and>
+ </condition>
+ </target>
+
+ <!-- set property javafx.enable.concurrent.external.runs=true to enable multiple runs of the same WebStart or Run-in-Browser project -->
+ <target name="-check-concurrent-html-runs" depends="-set-html-file">
+ <condition property="disable-concurrent-runs">
+ <or>
+ <not>
+ <and>
+ <isset property="javafx.enable.concurrent.external.runs"/>
+ <equals arg1="${javafx.enable.concurrent.external.runs}" arg2="true" trim="true"/>
+ </and>
+ </not>
+ <and>
+ <isset property="html-template-available"/>
+ <available file="${javafx.run.htmltemplate.processed}"/>
+ </and>
+ </or>
+ </condition>
+ <condition property="temp.run.html" value="${jfx.deployment.html}">
+ <isset property="disable-concurrent-runs"/>
+ </condition>
+ </target>
+ <target name="-warn-concurrent-html-runs" unless="disable-concurrent-runs">
+ <echo message="Note: Concurrent Run in Browser enabled.${line.separator}Temporary directory ${temp.run.dir}${line.separator}will remain unused when execution in browser has finished. Use project Clean to delete unused directories."/>
+ </target>
+
+ <target name="jfxbe-run" if="html-file-exists" depends="-mark-project-state-running,-clean-if-config-changed,-mark-project-needs-jnlp,-check-jdk-7u4or5-mac,jar,
+ -check-selected-browser-path,-set-html-file,-check-jfx-runtime,-check-concurrent-html-runs,-create-temp-run-dir"
+ description="Start JavaFX execution in browser">
+ <echo message="Executing ${temp.run.html} using ${javafx.run.inbrowser}"/>
+ <echo message="(${javafx.run.inbrowser.path})"/>
+ <exec executable="${javafx.run.inbrowser.path}">
+ <arg file="${temp.run.html}"/>
+ </exec>
+ <antcall target="-warn-concurrent-html-runs"/>
+ </target>
+
+ <target name="jfxbe-debug" if="html-file-exists+netbeans.home" depends="-mark-project-state-debugging,-clean-if-config-changed,-mark-project-needs-jnlp,
+ -check-jdk-7u4or5-mac,jar,-check-selected-browser-path,-set-html-file,-check-jfx-runtime,
+ -debug-start-debugger,-debug-jfxbe-debuggee" description="Debug JavaFX project in browser"/>
+
+ <target name="-debug-jfxbe-debuggee" depends="-init-debug-args">
+ <echo message="Executing ${jfx.deployment.html} in debug mode using ${javafx.run.inbrowser}"/>
+ <echo message="(${javafx.run.inbrowser.path})"/>
+ <exec executable="${javafx.run.inbrowser.path}">
+ <env key="_JPI_VM_OPTIONS" value="${debug-args-line} -Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <arg file="${jfx.deployment.html}"/>
+ </exec>
+ </target>
+
+ <target if="html-file-exists+netbeans.home" name="-profile-check-html">
+ <antcall target="-profile-check-1"/>
+ </target>
+
+ <target name="-do-jfxbe-profile" depends="-mark-project-state-profiling,-mark-project-needs-jnlp,
+ -check-jdk-7u4or5-mac,jar,-check-selected-browser-path,-set-html-file,-check-jfx-runtime">
+ <echo message="Executing ${jfx.deployment.html} in profile mode using ${javafx.run.inbrowser}"/>
+ <echo message="(${javafx.run.inbrowser.path})"/>
+ <property name="run.jvmargs.ide" value=""/>
+ <exec executable="${javafx.run.inbrowser.path}">
+ <env key="_JPI_VM_OPTIONS" value="${run.jvmargs.ide}"/>
+ <arg file="${jfx.deployment.html}"/>
+ </exec>
+ </target>
+
+ <target name="jfxbe-profile" if="profiler.configured"
+ depends="-profile-check-html"
+ description="Profile JavaFX project in browser">
+ <startprofiler/>
+ <antcall target="-do-jfxbe-profile"/>
+ </target>
+
+ <target name="jfxbe-run-noscript" depends="-set-fallback-no-javascript, jfxbe-run"/>
+
+ <target name="jfxbe-debug-noscript" depends="-set-fallback-no-javascript, jfxbe-debug"/>
+
+ <target name="jfxbe-profile-noscript" depends="-set-fallback-no-javascript, jfxbe-profile"/>
+
+
+</project>
--- /dev/null
+project.license=dusk3
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.processors.list=
+annotation.processing.run.all.processors=true
+annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
+application.title=DuskZ
+application.vendor=notzed
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+compile.on.save=true
+compile.on.save.unsupported.javafx=true
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/DuskZ.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+endorsed.classpath=
+excludes=
+includes=**
+# Non-JavaFX jar file creation is deactivated in JavaFX 2.0+ projects
+jar.archive.disabled=true
+jar.compress=false
+javac.classpath=\
+ ${javafx.runtime}/lib/jfxrt.jar:\
+ ${javafx.runtime}/lib/deploy.jar:\
+ ${javafx.runtime}/lib/javaws.jar:\
+ ${javafx.runtime}/lib/plugin.jar:\
+ ${reference.DuskCommon.jar}
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.processorpath=\
+ ${javac.classpath}
+javac.source=1.7
+javac.target=1.7
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+javac.test.processorpath=\
+ ${javac.test.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+javafx.binarycss=false
+javafx.deploy.adddesktopshortcut=false
+javafx.deploy.addstartmenushortcut=false
+javafx.deploy.allowoffline=true
+# If true, application update mode is set to 'background', if false, update mode is set to 'eager'
+javafx.deploy.backgroundupdate=false
+javafx.deploy.embedJNLP=true
+javafx.deploy.includeDT=true
+javafx.deploy.installpermanently=false
+javafx.deploy.permissionselevated=false
+# Set true to prevent creation of temporary copy of deployment artifacts before each run (disables concurrent runs)
+javafx.disable.concurrent.runs=false
+# Set true to enable multiple concurrent runs of the same WebStart or Run-in-Browser project
+javafx.enable.concurrent.external.runs=false
+# This is a JavaFX project
+javafx.enabled=true
+javafx.fallback.class=com.javafx.main.NoJavaFXFallback
+# Main class for JavaFX
+javafx.main.class=duskz.client.fx.DuskFX
+javafx.native.bundling.enabled=false
+javafx.native.bundling.type=none
+javafx.preloader.class=
+# This project does not use Preloader
+javafx.preloader.enabled=false
+javafx.preloader.jar.filename=
+javafx.preloader.jar.path=
+javafx.preloader.project.path=
+javafx.preloader.type=none
+# Set true for GlassFish only. Rebases manifest classpaths of JARs in lib dir. Not usable with signed JARs.
+javafx.rebase.libs=false
+javafx.run.height=600
+javafx.run.width=800
+javafx.runtime=${platforms.Default_JavaFX_Platform.javafx.runtime.home}
+javafx.sdk=${platforms.Default_JavaFX_Platform.javafx.sdk.home}
+javafx.signing.enabled=false
+javafx.signing.type=notsigned
+# Pre-JavaFX 2.0 WebStart is deactivated in JavaFX 2.0+ projects
+jnlp.enabled=false
+# Main class for Java launcher
+main.class=com.javafx.main.Main
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+mkdist.disabled=false
+platform.active=Default_JavaFX_Platform
+project.DuskCommon=../DuskCommon
+reference.DuskCommon.jar=${project.DuskCommon}/dist/DuskCommon.jar
+run.classpath=\
+ ${dist.jar}:\
+ ${javac.classpath}
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.java.j2seproject</type>
+ <configuration>
+ <buildExtensions xmlns="http://www.netbeans.org/ns/ant-build-extender/1">
+ <extension file="jfx-impl.xml" id="jfx">
+ <dependency dependsOn="-check-javafx" target="-init-check"/>
+ <dependency dependsOn="-jfx-copylibs" target="-post-jar"/>
+ <dependency dependsOn="-rebase-libs" target="-post-jar"/>
+ <dependency dependsOn="jfx-deployment" target="-post-jar"/>
+ <dependency dependsOn="jar" target="debug"/>
+ <dependency dependsOn="-jfx-copylibs" target="jar"/>
+ <dependency dependsOn="-rebase-libs" target="jar"/>
+ <dependency dependsOn="jar" target="profile"/>
+ <dependency dependsOn="jar" target="run"/>
+ </extension>
+ </buildExtensions>
+ <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
+ <name>DuskZ</name>
+ <explicit-platform explicit-source-supported="true"/>
+ <source-roots>
+ <root id="src.dir"/>
+ </source-roots>
+ <test-roots>
+ <root id="test.src.dir"/>
+ </test-roots>
+ </data>
+ <references xmlns="http://www.netbeans.org/ns/ant-project-references/1">
+ <reference>
+ <foreign-project>DuskCommon</foreign-project>
+ <artifact-type>jar</artifact-type>
+ <script>build.xml</script>
+ <target>jar</target>
+ <clean-target>clean</clean-target>
+ <id>jar</id>
+ </reference>
+ </references>
+ </configuration>
+</project>
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Changes
+ */
+package duskz.client;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Bookmark format is host:port
+ *
+ * TODO: store username too?
+ *
+ * @author notzed
+ */
+public class Bookmarks {
+
+ List<Bookmark> bookmarks = new ArrayList<>();
+
+ public List<Bookmark> getBookmarks() {
+ return bookmarks;
+ }
+
+ public void setBookmarks(List<Bookmark> bookmarks) {
+ this.bookmarks = bookmarks;
+ }
+
+ public Bookmarks() {
+ }
+
+ public void load(String path) throws IOException {
+ try (BufferedReader br = Files.newBufferedReader(Paths.get(path), Charset.forName("UTF-8"))) {
+ String l;
+
+ while ((l = br.readLine()) != null) {
+ try {
+ bookmarks.add(Bookmark.valueOf(l));
+ } catch (NumberFormatException ex) {
+ }
+ }
+ } catch (NoSuchFileException x) {
+ // ignore it
+ }
+ }
+
+ public void save(String path) throws IOException {
+ try (BufferedWriter br = Files.newBufferedWriter(Paths.get(path), Charset.forName("UTF-8"), StandardOpenOption.CREATE,
+ StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {
+ for (Bookmark b : bookmarks) {
+ b.write(br);
+ }
+ }
+ }
+
+ public static class Bookmark {
+
+ public String host;
+ public int port;
+
+ public Bookmark(String host, int port) {
+ this.host = host;
+ this.port = port;
+ }
+
+ public static Bookmark valueOf(String v) {
+ int p = v.indexOf(':');
+ if (p != -1) {
+ return new Bookmark(v.substring(0, p), Integer.valueOf(v.substring(p + 1)));
+ } else {
+ return new Bookmark(v, 7400);
+ }
+ }
+
+ private void write(BufferedWriter br) throws IOException {
+ br.write(host);
+ br.write(':');
+ br.write(Integer.toString(port));
+ br.write('\n');
+ }
+
+ @Override
+ public String toString() {
+ return host + ":" + port;
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Changes
+ */
+package duskz.client;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+/**
+ * Client map has a fixed set of tiles for the background. And then a bunch of
+ * entities roaming across it.
+ *
+ * I experimented here with a different implementation to the server map in that
+ * the entities by location uses a hash table rather than an array. This allows
+ * me to reference them by absolute coordinates which simplifies a lot of the
+ * code.
+ *
+ * @author notzed
+ */
+public class ClientMap {
+
+ /**
+ * Offset of map (top-left corner)
+ */
+ public int offx, offy;
+ /**
+ * Tile indices for images
+ */
+ private short[] tiles;
+ /**
+ * Entities by id
+ */
+ private HashMap<Long, Entity> entityByID = new HashMap<>();
+ /**
+ * Entities by name
+ * TODO: If names do not need unique 'numbers' then this
+ * index can be completely removed.
+ */
+ private HashMap<String, List<Entity>> entityByName = new HashMap<>();
+ /**
+ * Enities by location. Location is encoded as ( y << 16) | x
+ */
+ private HashMap<Integer, List<Entity>> entityByLocation = new HashMap<>();
+ /**
+ * Width of map shown
+ */
+ public final int cols;
+ /**
+ * Height of map shown
+ */
+ public final int rows;
+
+ public ClientMap(int cols, int rows) {
+ this.cols = cols;
+ this.rows = rows;
+
+ tiles = new short[cols * rows];
+ }
+
+ public Collection<Entity> getEntities() {
+ return entityByID.values();
+ }
+
+ public Collection<Entity> getEntities(int x, int y) {
+ return entityByLocation.get(locationKey(x, y));
+ }
+
+ public int getTile(int x, int y) {
+ return tiles[x + y * cols];
+ }
+
+ public void setTile(int x, int y, int tile) {
+ tiles[x + y * cols] = (short) tile;
+ }
+
+ private Integer locationKey(int x, int y) {
+ return (y << 16) | x;
+ }
+
+ private Integer locationKey(Entity e) {
+ return (e.locy << 16) | e.locx;
+ }
+
+ public int mapToLocalX(int x) {
+ return x - offx;
+ }
+
+ public int mapToLocalY(int y) {
+ return y - offy;
+ }
+
+ private void addLocation(Entity e) {
+ // Index by absolute location.
+ Integer loc = locationKey(e);
+ List<Entity> bypos = entityByLocation.get(loc);
+ if (bypos == null) {
+ bypos = new ArrayList<>();
+ entityByLocation.put(loc, bypos);
+ }
+ bypos.add(e);
+ }
+
+ private void removeLocation(Entity e) {
+ Integer loc = locationKey(e);
+ List<Entity> bypos = entityByLocation.get(loc);
+
+ if (bypos == null || !bypos.remove(e))
+ throw new RuntimeException("Entity not in location index");
+
+ if (bypos.isEmpty())
+ entityByLocation.remove(loc);
+ }
+
+ public synchronized void addEntity(Entity e) {
+ if (entityByID.containsKey(e.ID)) {
+ throw new RuntimeException("entity already in table " + e.ID + " " + e.strName);
+ }
+
+ entityByID.put(e.ID, e);
+
+ // Add byname index, and re-number if required
+ List<Entity> byname = entityByName.get(e.getSimpleName());
+ if (byname == null) {
+ byname = new ArrayList<>();
+ entityByName.put(e.getSimpleName(), byname);
+ }
+ byname.add(e);
+ //for (int i = 0; i < byname.size(); i++)
+ // byname.get(i).intNum = i;
+
+ addLocation(e);
+ }
+
+ public synchronized void moveEntity(Entity e, int tox, int toy) {
+ removeLocation(e);
+ e.locx = tox;
+ e.locy = toy;
+ addLocation(e);
+ }
+
+ public synchronized void removeEntity(Entity e) {
+ removeEntity(e.ID);
+ }
+
+ public synchronized void removeEntity(long id) {
+ Entity e = entityByID.remove(id);
+
+ if (e == null) {
+ System.out.println("removeEntity: no such entity " + id);
+ return;
+ }
+
+ List<Entity> byname = entityByName.get(e.getSimpleName());
+ byname.remove(e);
+ if (byname.isEmpty()) {
+ entityByName.remove(e.getSimpleName());
+ } else {
+ //for (int i = 0; i < byname.size(); i++)
+ // byname.get(i).intNum = i;
+ }
+
+ removeLocation(e);
+ }
+
+ public synchronized Entity getEntity(long id) {
+ return entityByID.get(id);
+ }
+
+ boolean inside(int x, int y) {
+ int lx = x - offx;
+ int ly = y - offy;
+
+ return lx >= 0 && lx < cols
+ && ly >= 0 && ly < rows;
+ }
+
+ public synchronized void updateTiles(int offx, int offy, DataInputStream instream) throws IOException {
+ //for (int x = 0; x < cols; x++) {
+ // for (int y = 0; y < rows; y++) {
+ // setTile(x, y, Short.parseShort(instream.readLine()));
+ // }
+ //}
+ int length = instream.readInt();
+ if (length != cols * rows) {
+ throw new IOException("Protocol error incorrect map size");
+ }
+ for (int y = 0; y < rows; y++) {
+ for (int x = 0; x < cols; x++) {
+ setTile(x, y, instream.readShort());
+ }
+ }
+
+ this.offx = offx;
+ this.offy = offy;
+
+ // Prune out of range thingies
+ List<Entity> removing = new ArrayList<>();
+ for (Entry<Integer, List<Entity>> es : entityByLocation.entrySet()) {
+ int ex = es.getKey() & 0xffff;
+ int ey = (es.getKey() >> 16) & 0xffff;
+
+ System.out.printf("check inside %d,%d = %s\n", ex, ey, inside(ex, ey));
+
+ if (!inside(ex, ey)) {
+ removing.addAll(es.getValue());
+ }
+ }
+
+ // TODO: this could be optimised
+ // TODO: does the server need to know this
+ if (!removing.isEmpty()) {
+ System.out.println("offset: " + this.offx + "," + this.offy);
+ for (Entity e : removing) {
+ System.out.println("removing out of range :" + e);
+ removeEntity(e);
+ }
+ }
+ }
+
+ public synchronized void updateTiles(int offx, int offy, short[] tiles) throws IOException {
+ //for (int x = 0; x < cols; x++) {
+ // for (int y = 0; y < rows; y++) {
+ // setTile(x, y, Short.parseShort(instream.readLine()));
+ // }
+ //}
+ if (tiles.length != rows * cols) {
+ throw new IOException("Protocol error incorrect map size");
+ }
+ System.arraycopy(tiles, 0, this.tiles, 0, tiles.length);
+
+ this.offx = offx;
+ this.offy = offy;
+
+ // Prune out of range thingies
+ List<Entity> removing = new ArrayList<>();
+ for (Entry<Integer, List<Entity>> es : entityByLocation.entrySet()) {
+ int ex = es.getKey() & 0xffff;
+ int ey = (es.getKey() >> 16) & 0xffff;
+
+ System.out.printf("check inside %d,%d = %s\n", ex, ey, inside(ex, ey));
+
+ if (!inside(ex, ey)) {
+ removing.addAll(es.getValue());
+ }
+ }
+
+ // TODO: this could be optimised
+ // TODO: does the server need to know this
+ if (!removing.isEmpty()) {
+ System.out.println("offset: " + this.offx + "," + this.offy);
+ for (Entity e : removing) {
+ System.out.println("removing out of range :" + e);
+ removeEntity(e);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Changes
+ */
+package duskz.client;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+
+/**
+ * Utility for loading game objects from jar file
+ * and managing them
+ *
+ * TODO: i couldn't work out how to do generics with the inner class thing
+ *
+ * @author notzed
+ */
+public class DataManager {
+
+ String source;
+ protected ImageSet[] tilesets;
+
+ public DataManager(String source) {
+ this.source = source;
+ }
+
+ public void open() throws IOException {
+ tilesets = getImageSet("tilesets");
+ // TODO: sprites, etc.
+
+ for (ImageSet is : tilesets)
+ is.load();
+ }
+
+ private int getInt(Attributes a, int index, String name) {
+ try {
+ return Integer.valueOf(a.getValue(index + "_" + name));
+ } catch (NumberFormatException x) {
+ return -1;
+ }
+ }
+
+ protected ImageSet createImageSet() {
+ return new ImageSet();
+ }
+
+ JarInputStream openJar() throws IOException {
+ return new JarInputStream(new FileInputStream(source));
+ }
+
+ public ImageSet[] getImageSet(String setName) throws IOException {
+ List<ImageSet> list;
+ try (JarInputStream jis = openJar()) {
+ list = new ArrayList<>();
+ Manifest man = jis.getManifest();
+ Attributes a = man.getAttributes(setName);
+ int count = Integer.valueOf(a.getValue("count"));
+ for (int i = 0; i < count; i++) {
+ ImageSet set = createImageSet();
+
+ set.name = a.getValue(i + "_name");
+ set.source = a.getValue(i + "_source");
+ set.gid = getInt(a, i, "gid");
+ set.count = getInt(a, i, "count");
+ set.width = getInt(a, i, "width");
+ set.height = getInt(a, i, "height");
+
+ // Load it straight away?
+
+ list.add(set);
+ }
+ }
+
+ return list.toArray(new ImageSet[list.size()]);
+ }
+
+ public class ImageSet {
+
+ public String name;
+ public String source;
+ public int gid;
+ public int count;
+ public int width;
+ public int height;
+
+ public ImageSet() {
+ }
+
+ public void load() throws IOException {
+ }
+
+ public InputStream getInputStream() throws IOException {
+ JarInputStream jis = null;
+ try {
+ jis = openJar();
+ JarEntry je;
+
+ System.out.println("Looking for: " + source);
+
+ while ((je = jis.getNextJarEntry()) != null) {
+ System.out.println("je = " + je.getName());
+ if (je.getName().equals(source))
+ return jis;
+ }
+ jis.close();
+ throw new FileNotFoundException(source);
+ } catch (IOException ex) {
+ if (jis != null)
+ jis.close();
+ throw ex;
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ. If not, see <http://www.gnu.org/licenses/>.
+ */
+package duskz.client;
+
+/**
+ * Enumeration for direction commands.
+ * @author notzed
+ */
+public enum Direction {
+ North("n"),
+ South("s"),
+ East("e"),
+ West("w");
+
+ String cmd;
+ private Direction(String cmd) {
+ this.cmd = cmd;
+ }
+
+
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Special Thanks to:
+ * Randall Leeds for the following code portions
+ * as well as many other small changes and deprecation fixes:
+ * Float/Unfloat
+ * Joe Alloway for shadowed text and the !set command
+ *
+ * Changes
+ * Feb-2013 Michael Zucchi - modernised java, cleanup, abstracted the GUI behind
+ * an interface. Abstracted most commands. Added some binary protocol changes.
+ * Track the player id for better battles.
+ */
+package duskz.client;
+
+import duskz.protocol.MessageType;
+import duskz.protocol.ServerMessage;
+import duskz.protocol.ServerMessage.EntityMessage;
+import java.io.*;
+import java.net.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * TODO: I've removed <rgb r g b>text</rgb> colour text for now, implementation
+ * was poor TODO: applet stuff is removed FIXME: sound is all disabled
+ *
+ * @author notzed
+ */
+public class Dusk implements Runnable {
+
+ public final static boolean dumpRaw = false;
+ static String strVersion = "2.7.1.W3";
+ Status status = new Status();
+ long loncash;
+ boolean loaded,
+ blnMenuRefresh,
+ connected = false,
+ blnApplet;
+ int intMusicTypes;
+ int intNumSongs[];
+ // FIXME: applet will have a different frontend or something
+ //AudioClip audSFX[], audMusic[][];
+ //AudioClip audMusicPlaying;
+ String rcLocation;
+ List<TransactionItem> buyList = new ArrayList<>();
+ List<TransactionItem> sellList = new ArrayList<>();
+ Equipment worn = new Equipment();
+ Socket socket;
+ DataOutputStream outstream;
+ DataInputStream instream;
+ int mapSize = 11;
+ ClientMap map;
+ boolean intStep,
+ blnMusic = true;
+ Thread thrRun;
+ int tileSize = 32;
+ int spriteSize = 64;
+ GUI frame;
+ String address = "dusk.wesowin.org";
+ int port = 7423;
+
+ public Dusk(GUI gui) {
+ frame = gui;
+ frame.setGame(this);
+ }
+
+ public void startUp() {
+ try {
+ //frame.initComponents();
+ //frame.setVisible(true);
+ frame.logClear();
+ frame.log("Dusk Client v" + strVersion + " -- http://FIXME/\n");
+ frame.log("You are using Java version " + System.getProperty("java.version") + "\n");
+
+ if (blnApplet) {
+ //address = appShell.getParameter("address");
+ //port = Integer.parseInt(appShell.getParameter("port"));
+ connect();
+ } else {
+ frame.showLogin();
+ }
+ //thrGraphics = new GraphicsThread(this);
+ // TODO: check if i need to set map images here
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // Main entry point
+ //static public void main(String[] args) {
+ // new Dusk();
+ //}
+ void connect() {
+ throw new UnsupportedOperationException();
+ }
+
+ // initial cut at automatic login stuff
+ // probably want to fix server to handle login/new account stuff separately
+ enum State {
+ // not connected
+
+ Unconnected,
+ // tcp connection made
+ Connected,
+ // Username sent
+ Username,
+ // Create a new user
+ Create,
+ // Password sent
+ Password,
+ // Password accepted
+ Ready,
+ // Waiting for race selection
+ SelectRace,
+ }
+ State state = State.Unconnected;
+ String pass;
+
+ public void connect(String address, int port, String user, String pass) {
+ // Connect to Server
+ try {
+ socket = new Socket(address, port);
+ outstream = new DataOutputStream(socket.getOutputStream());
+ instream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
+ log("Please enter your character name or the name of a new character: \n");
+
+ state = State.Connected;
+
+ // Load Images and start checking for incoming commands
+ thrRun = new Thread(this);
+ thrRun.start();
+ connected = true;
+ //Initialize objects
+ map = new ClientMap(11, 11);
+ buyList.clear();
+ sellList.clear();
+
+ this.pass = pass;
+ state = State.Username;
+ command(user);
+ } catch (Exception e) {
+ log("Error connecting to server: " + e.toString() + "\n");
+ return;
+ }
+ }
+
+ /**
+ * FIXME: all needs a rewrite
+ *
+ * @param entStore
+ */
+ // add the thing, this renumbers any that have the same name
+ void addEntity(Entity entStore) {
+ System.out.println("Add entity: " + entStore.ID + " " + entStore.strName);
+ map.addEntity(entStore);
+
+ // FIXME: call rement if it was out of range so the server knows
+ }
+
+ Entity findEntity(long id) {
+ return map.getEntity(id);
+ }
+
+ void removeEntity(long id) {
+ map.removeEntity(id);
+ }
+
+ void removeEntity(Entity entStore) {
+ map.removeEntity(entStore);
+ }
+
+ /**
+ * Read a . terminated list from server
+ *
+ * @return
+ */
+ List<String> readList() throws IOException {
+ List<String> l = new ArrayList<>();
+
+ String s = instream.readLine();
+ while (!s.equals(".")) {
+ l.add(s);
+ s = instream.readLine();
+ }
+ return l;
+ }
+
+ String readContent(String end) throws IOException {
+ StringBuilder sb = new StringBuilder();
+ String s = instream.readLine();
+
+ while (!s.equals(end)) {
+ sb.append(s).append('\n');
+ s = instream.readLine();
+ }
+ return sb.toString();
+ }
+
+ //Thread to process incoming commands
+ public void run() {
+ int incoming = 0;
+ while (incoming != -1) {
+ try {
+ // Handle incoming messages from Server
+// incoming = stmIn.readByte();
+ incoming = instream.read();
+
+ if (incoming == -1) {
+ continue;
+ }
+
+ MessageType type = MessageType.fromServer(incoming);
+
+ System.out.println("state " + state + " incoming = " + type);
+
+ // Hack to auto-login to server
+ switch (state) {
+ case Username:
+ if (type == MessageType.Chat) {
+ String s = instream.readLine();
+ System.out.println("username: text: " + s);
+ if (s.equals("enter your password:")) {
+ state = State.Password;
+ command(pass);
+ } else if (s.endsWith("Is that correct? (yes/no)")) {
+ // "new user" shit
+ state = state.Create;
+ command("yes");
+ }
+ }
+ continue;
+ case Password:
+ if (type == MessageType.Chat) {
+ String s = instream.readLine();
+ System.out.println("password: text: " + s);
+ if (s.equals("Login Accepted.")) {
+ state = State.Ready;
+ frame.loginOk();
+ } else if (s.equals("Incorrect Password.")) {
+ // blah blah what now?
+ state = state.Connected;
+ }
+ }
+ continue;
+ case Create:
+ if (type == MessageType.Chat) {
+ String s = instream.readLine();
+ System.out.println("create: text: " + s);
+ if (s.equals("Enter a new password:")) {
+ command(pass);
+ } else if (s.equals("Confirm that password:")) {
+ //state = State.Password;
+ command(pass);
+ } else if (s.equals("Login Accepted.")) {
+ // this should now ask for a race
+ state = State.Ready;
+ frame.loginOk();
+ }
+ // TODO: find out what happens if that doesn't work
+ }
+ continue;
+ case SelectRace:
+ switch (type) {
+ case ChooseRace:
+ // Bad choice, try again
+ handleChooseRace(instream);
+ continue;
+ default:
+ state = State.Ready;
+ // any other message drop through to process
+ }
+ break;
+ }
+
+ switch (type) {
+ case Quit: //Quit
+ {
+ loaded = false;
+ connected = false;
+ socket.close();
+ return;
+ }
+ case UpdateImages: //update Images
+ {
+ rcLocation = instream.readLine();
+ // FIXME: not if applet or something?
+ rcLocation = "rc/" + rcLocation;
+
+ frame.setImages(new File(rcLocation + "/images/map.gif").toURI().toString(), 32,
+ new File(rcLocation + "/images/players.gif").toURI().toString(), 64,
+ new File(rcLocation + "/images/sprites.gif").toURI().toString(), 64);
+ update();
+ break;
+ }
+ case UpdateLocMap: {
+ /*
+ status.updateLocation(instream);
+ System.out.printf("Updating map to %d %d map size %d %d\n",
+ status.locx, status.locy, mapSize, mapSize);
+ map.updateTiles(status.locx - (map.cols - 1) / 2, status.locy - (map.rows - 1) / 2, instream);
+ */
+ ServerMessage.MapMessage msg = ServerMessage.MapMessage.decode(instream);
+ status.updateLocation(msg.x, msg.y);
+ map.updateTiles(msg.x - (map.cols - 1) / 2, msg.y - (map.rows - 1) / 2, msg.map);
+ update();
+ frame.setStatus(status);
+ //frame.info.setText("HP: " + inthp + "/" + intmaxhp + " MP: " + intsp + "/" + intmaxsp + " Loc: " + LocX + "/" + LocY);
+ buyList.clear();
+ reloadChoiceLookGetAttack();
+ //paint();
+ break;
+ }
+ case Chat: //incoming chat
+ {
+ chat(instream.readLine() + "\n");
+ break;
+ }
+ case AddEntity: //add Entity
+ {
+ /*
+ String s = instream.readLine();
+ int etype = Byte.parseByte(instream.readLine());
+ Entity ent = null;
+ if (etype == 0) {
+ try {
+ ent = new Entity(s,
+ Long.parseLong(instream.readLine()),
+ Integer.parseInt(instream.readLine()),
+ Integer.parseInt(instream.readLine()),
+ Integer.parseInt(instream.readLine()),
+ Integer.parseInt(instream.readLine()),
+ etype);
+ } catch (NullPointerException e) {
+ ent = null;
+ }
+ } else {
+ try {
+ ent = new Entity(s,
+ Long.parseLong(instream.readLine()),
+ Integer.parseInt(instream.readLine()),
+ Integer.parseInt(instream.readLine()),
+ Integer.parseInt(instream.readLine()),
+ -1,
+ etype);
+ } catch (NullPointerException e) {
+ ent = null;
+ }
+ }*/
+ EntityMessage msg = ServerMessage.EntityMessage.decode(type, instream);
+ if (msg != null) {
+ addEntity(new Entity(msg));
+ }
+ reloadChoiceLookGetAttack();
+ update();
+ break;
+ }
+ case UpdateStats: //update Stats
+ {
+ status.updateStatus(instream);
+ frame.setStatus(status);
+ break;
+ }
+ case UpdateItems: //update Items
+ {
+ worn.updateAvailable(instream);
+ frame.setDropList(worn.all);
+ frame.setEquipment(worn);
+ break;
+ }
+ case UpdateEquipment: //update Equipment
+ {
+ worn.updateWorn(instream);
+ frame.setEquipment(worn);
+ break;
+ }
+ case UpdateInfo: //update Stats
+ {
+ try {
+ StringBuilder sb = new StringBuilder();
+ String s = instream.readLine();
+ while (!s.equals(".")) {
+ sb.append(s);
+ sb.append("\n");
+ s = instream.readLine();
+ }
+ frame.setStats(sb.toString());
+ } catch (Exception e) {
+ System.err.println("Error loading stats" + e.toString());
+ }
+ break;
+ }
+ case Halt: //halt
+ {
+ loaded = false;
+ break;
+ }
+ case UpdateActions: //update Actions
+ {
+ frame.setActionList(readList());
+ break;
+ }
+ case LoadMusic: //load music
+ {
+ try {
+ // FIXME; applet
+ /*
+ if (blnApplet) {
+ log("Loading music.\n");
+ intMusicTypes = Integer.parseInt(instream.readLine());
+ audMusic = new AudioClip[intMusicTypes][];
+ intNumSongs = new int[intMusicTypes];
+ for (intStore = 0; intStore < intMusicTypes; intStore++) {
+ intNumSongs[intStore] = Integer.parseInt(instream.readLine());
+ audMusic[intStore] = new AudioClip[intNumSongs[intStore]];
+ for (intStore2 = 0; intStore2 < intNumSongs[intStore]; intStore2++) {
+ String s = instream.readLine();
+ try {
+ //audMusic[intStore][intStore2] = appShell.getAudioClip(new URL(strStore));
+ while (audMusic[intStore][intStore2] == null) {
+ }
+ } catch (Exception e) {
+ System.err.println("Error while trying to load music file " + s + ":" + e.toString());
+ }
+ }
+ }
+ log("Music loaded.\n");
+ }*/
+ } catch (Exception e) {
+ blnMusic = false;
+ log("Your java virtual machine does not support midi music\n");
+ System.err.println("Error while trying to load music files:" + e.toString());
+ }
+ break;
+ }
+ case PlayMusic: //play music
+ {
+ if (blnMusic) {
+ /* FIXME: sound
+ try {
+ intStore = Integer.parseInt(instream.readLine());
+ if (audMusicPlaying != null) {
+ audMusicPlaying.stop();
+ }
+ audMusicPlaying = audMusic[intStore][(int) (Math.random() * intNumSongs[intStore])];
+ audMusicPlaying.loop();
+ } catch (Exception e) {
+ System.err.println("Error while trying to play music file:" + e.toString());
+ }*/
+ }
+ break;
+ }
+ case Ping: //stillThere?
+ {
+ outstream.writeBytes("notdead\n");
+ break;
+ }
+ case Proceed: //proceed
+ {
+ status.id = Long.parseLong(instream.readLine());
+ loaded = true;
+ break;
+ }
+ case PlaySound: //play sfx
+ {
+ try {
+ //audSFX[Integer.parseInt(instream.readLine())].play();
+ } catch (Exception e) {
+ }
+ break;
+ }
+ case RemoveEntity: //remove entity
+ {
+ long id = Long.valueOf(instream.readLine()).longValue();
+
+ removeEntity(id);
+ reloadChoiceLookGetAttack();
+ update();
+ break;
+ }
+ case UpdateMerchant: //update Merchant
+ {
+ buyList = TransactionItem.createItems(readList());
+ frame.setBuyList(buyList);
+ break;
+ }
+ case EditText: //view/edit
+ {
+ String name = instream.readLine();
+ frame.visitFile(name, readContent("--EOF--"), true);
+ break;
+ }
+ case ResizeMap: //resize Map
+ {
+ mapSize = Integer.parseInt(instream.readLine());
+ map = new ClientMap(mapSize, mapSize);
+ if (blnApplet) {
+ outstream.writeBytes("appletimages\n");
+ } else {
+ outstream.writeBytes("applicationimages\n");
+ }
+ //scaleWindow();
+ break;
+ }
+ case ViewText: //view/no-edit
+ {
+ String name = instream.readLine();
+ frame.visitFile(name, readContent("--EOF--"), false);
+ break;
+ }
+ case ExitMerchant: //offMerchant
+ {
+ frame.exitShop();
+ buyList.clear();
+ sellList.clear();
+ break;
+ }
+ case UpdateSell: //update Sell
+ {
+ sellList = TransactionItem.createItems(readList());
+ frame.setSellList(sellList);
+ break;
+ }
+ case ColourChat: //colour chat
+ {
+ // FIXME: re-implement colour, or probably fix it (hex codes)
+ instream.readLine();
+ instream.readLine();
+ instream.readLine();
+ chat(instream.readLine() + "\n");
+ break;
+ }
+ case MoveNorth: //move north
+ {
+ long ID = Long.parseLong(instream.readLine());
+
+ handleMove(ID, 1, 0, -1, 0);
+ break;
+ }
+ case MoveSouth: //move south
+ {
+ long ID = Long.parseLong(instream.readLine());
+
+ handleMove(ID, 3, 0, 1, 1);
+ break;
+ }
+ case MoveWest: //move west
+ {
+ long ID = Long.parseLong(instream.readLine());
+
+ handleMove(ID, 5, -1, 0, 2);
+ break;
+ }
+ case MoveEast: //move east
+ {
+ long ID = Long.parseLong(instream.readLine());
+
+ handleMove(ID, 7, 1, 0, 3);
+ break;
+ }
+ case UpdateRange: //update range
+ {
+ status.range = Integer.parseInt(instream.readLine());
+ break;
+ }
+ case SetFlag: //set flag
+ {
+ long id = Long.valueOf(instream.readLine()).longValue();
+ int flags = Integer.parseInt(instream.readLine());
+
+ Entity e = map.getEntity(id);
+ if (e != null) {
+ e.intFlag = flags;
+ update();
+ } else {
+ log("Error: set flag on unknown entity: " + id);
+ }
+ break;
+ }
+ case ClearFlags: //clear all flags
+ {
+ // FIXME: hideinfo?
+ synchronized (map) {
+ for (Entity e : map.getEntities()) {
+ e.intFlag = 0;
+ }
+ }
+ update();
+ break;
+ }
+ case StartBattle: //show battle window and clear text
+ {
+ // FIXME: no battle popup window at the moment
+ String s = instream.readLine();
+ battle("Battle started: " + s + "\n");
+ break;
+ }
+ case UpdateBattle: //show battle window and update title
+ {
+ // FIXME: no battle popup window at the moment
+ String s = instream.readLine();
+ battle("Battle status: " + s + "\n");
+ break;
+ }
+ case LogBattle: //add text to battle window
+ {
+ // FIXME: no battle popup window at the moment
+ String s = instream.readLine();
+ battle(s + "\n");
+ break;
+ }
+ case ChooseRace:
+ handleChooseRace(instream);
+ break;
+ case HitEntity: {
+ long toID = Long.valueOf(instream.readLine());
+ int delta = -Integer.valueOf(instream.readLine());
+ int newhp = Integer.valueOf(instream.readLine());
+ int tothp = Integer.valueOf(instream.readLine());
+ long fromID = Long.valueOf(instream.readLine());
+ String how = instream.readLine();
+
+ String s;
+ do {
+ s = instream.readLine();
+ } while (!s.equals("."));
+
+ System.out.printf("entity %d %s delta %d hp %d/%d\n",
+ toID, how, delta, newhp, tothp);
+
+ // TODO: I should have who from/to this damage is
+ Entity f = findEntity(fromID);
+ Entity e = findEntity(toID);
+ if (e != null) {
+ double xloc = map.mapToLocalX(e.locx),
+ yloc = map.mapToLocalY(e.locy);
+
+ // Get angle to entity from player
+ double a = Math.PI;
+ if (f != null) {
+ a = Math.atan2(e.locy - f.locy, e.locx - f.locx);
+ }
+
+ frame.damageEntity(e, a, xloc * tileSize, yloc * tileSize, delta, how);
+ } else {
+ System.out.println("Unknown entity");
+ }
+
+ break;
+ }
+ }
+ } catch (Exception e) {
+ System.err.println("Error at run() with value " + incoming + " : " + e.toString());
+ e.printStackTrace(System.out);
+
+ log("Error at run() with value " + incoming + " : " + e.toString() + "\n");
+ connected = false;
+ return;
+ }
+ }
+ System.err.println("Error at run() with value " + incoming);
+ }
+
+ private void handleMove(long ID, int step, int dx, int dy, int dir) {
+ Entity e = map.getEntity(ID);
+
+ if (e == null) {
+ System.out.println("move unknown entity: " + ID);
+ return;
+ }
+
+ map.moveEntity(e, e.locx + dx, e.locy + dy);
+ if (e.intStep != -1) {
+ // Toggle through the 2 animations for movement
+ if (e.intMoveDirection == dir) {
+ e.intStep ^= 1;
+ } else {
+ e.intStep = step;
+ e.intMoveDirection = dir;
+ }
+ }
+ reloadChoiceAttack();
+ // TODO: find out what this is for
+ //if (addit) {
+ // thrGraphics.addEntityToMove(ent, dir);
+ //}
+ // HACK: Don't update the screen display if the user moves, attempted
+ // fix at flicker-on-move stuff.
+ // The server should always send an UpdateLocMap every time
+ if (ID != status.id) {
+ update();
+ }
+ }
+
+ private void handleChooseRace(DataInputStream in) throws IOException {
+ List<String> races = new ArrayList<>();
+ String prompt = in.readLine();
+ String l = in.readLine();
+ while (!l.equals(".")) {
+ races.add(l);
+ l = in.readLine();
+ }
+ state = State.SelectRace;
+ frame.chooseRace(prompt, races);
+ }
+
+ public void chooseRace(String race) {
+ if (state == State.SelectRace) {
+ command(race);
+ }
+ }
+
+ // TBD - use the individual functions
+ public void reloadChoiceLookGetAttack() {
+ final ArrayList<Entity> looks = new ArrayList<>();
+ final ArrayList<Entity> gets = new ArrayList<>();
+ final ArrayList<Entity> attacks = new ArrayList<>();
+
+ synchronized (map) {
+ for (Entity e : map.getEntities()) {
+ if (status.canLook(e))
+ looks.add(e);
+
+ if (status.canTake(e))
+ gets.add(e);
+
+ if (status.canAttack(e))
+ attacks.add(e);
+ }
+ }
+
+ frame.setLookList(looks);
+ frame.setAttackList(attacks);
+ frame.setTakeList(gets);
+ }
+
+ public void reloadChoiceLook() {
+ final ArrayList<Entity> looks = new ArrayList<>();
+
+ synchronized (map) {
+ for (Entity e : map.getEntities()) {
+ if (status.canLook(e))
+ looks.add(e);
+ }
+ }
+ frame.setLookList(looks);
+ }
+
+ public void reloadChoiceAttack() {
+ final ArrayList<Entity> attacks = new ArrayList<>();
+
+ synchronized (map) {
+ for (Entity e : map.getEntities()) {
+ if (status.canAttack(e))
+ attacks.add(e);
+ }
+ }
+ frame.setAttackList(attacks);
+ }
+
+ public void reloadChoiceGet() {
+ final ArrayList<Entity> gets = new ArrayList<>();
+
+ synchronized (map) {
+ for (Entity e : map.getEntities()) {
+ if (status.canTake(e))
+ gets.add(e);
+ }
+ }
+ frame.setTakeList(gets);
+ }
+
+ public boolean isConnected() {
+ return connected;
+ }
+
+ public boolean isLoaded() {
+ return loaded;
+ }
+
+ public int getTileSize() {
+ return tileSize;
+ }
+
+ /**
+ * Offset y to origin of displayed map
+ *
+ * @return
+ */
+ public int getMapOffsetX() {
+ return map.offx;
+ }
+
+ /**
+ * Offset y to origin of displayed map
+ *
+ * @return
+ */
+ public int getMapOffsetY() {
+ return map.offy;
+ }
+
+ public void userconnect() {
+ //frame.frmConnect.show();
+ //frame.frmConnect.setSize(350, 200);
+ System.out.println("user ocnnect not implemented - quit and restart");
+ }
+
+ public void equipment() {
+ frame.manageEquipment(worn);
+ }
+
+ public void merchant() {
+ frame.enterShop("Merchant", buyList, sellList);
+ }
+
+ // these all do the same thing at the moment, but could allow
+ // for alternative output for various things
+ // FIXME: chat needs the source id as well
+ public void chat(String txt) {
+ frame.log(txt);
+ }
+
+ public void battle(String txt) {
+ System.out.println("battle: " + txt);
+ frame.log(txt);
+ }
+
+ public void log(String txt) {
+ frame.log(txt);
+ }
+
+ public void logout() {
+ try {
+ if (connected) {
+ outstream.writeBytes("quit\n");
+ }
+ } catch (Exception exc) {
+ }
+ try {
+ socket.close();
+ } catch (Exception exc) {
+ }
+ socket = null;
+ connected = false;
+ }
+
+ public void quit() {
+ try {
+ if (connected) {
+ outstream.writeBytes("quit\n");
+ }
+ } catch (Exception exc) {
+ }
+ try {
+ socket.close();
+ } catch (Exception exc) {
+ }
+ System.gc();
+ if (blnApplet) {
+ //appShell.destroy();
+ } else {
+ // FIXME: wrong!
+ System.exit(0);
+ }
+
+ }
+
+ //Display graphics
+ public void update() {
+ synchronized (map) {
+ frame.updateMap(map);
+ }
+ }
+
+ private void docmd(String cmd) {
+ System.out.println("send command: " + cmd);
+ try {
+ outstream.writeBytes(cmd);
+ } catch (IOException ex) {
+ // TODO: close connection here
+ Logger.getLogger(Dusk.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ public void command(String what) {
+ docmd(what + "\n");
+ }
+
+ public void command(String what, String params) {
+ docmd(what + " " + params + "\n");
+ }
+
+ public void move(Direction dir) {
+ command(dir.cmd);
+ }
+
+ public void moveTo(int dx, int dy) {
+ //Move to location
+ try {
+ System.out.println("goto " + dx + "," + dy);
+ outstream.writeBytes("goto " + dx + " " + dy + "\n");
+ } catch (Exception e) {
+ frame.log("Error in goto %d,%d: %s", dx, dy, e);
+ }
+ }
+
+ public void buy(TransactionItem item, int quantity) {
+ command("buy " + quantity + " " + item.name);
+ }
+
+ public void sell(TransactionItem item, int quantity) {
+ command("sell " + quantity + " " + item.name);
+ }
+
+ // TODO: find out why these uses the base name and ignores the numbers.
+ public void attack(Entity e) {
+ command("a " + e.ID);
+ }
+
+ public void look(Entity e) {
+ command("look " + e.ID);
+ }
+
+ public void take(Entity e) {
+ command("get " + e.ID);
+ }
+
+ public void drop(String what) {
+ command("drop " + what);
+ }
+
+ public void wear(String what) {
+ command("wear " + what);
+ }
+
+ public void unwear(String what) {
+ command("unwear " + what);
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - some helper/accessors.
+ */
+package duskz.client;
+
+import duskz.protocol.ServerMessage;
+
+public class Entity {
+
+ public String strName;
+ public int locx,
+ locy;
+ public int intType,
+ intNum = 0,
+ intStep = -1,
+ intImage = 0,
+ intTicks,
+ intMoveDirection = -1,
+ /*intMoveDirection
+ 0 north
+ 1 south
+ 2 west
+ 3 east
+ */
+ intFlag = 0;
+ /*intFlag
+ 0 none
+ 1 ally
+ 2 enemy
+ */
+ long ID;
+ Entity entNext = null;
+
+ public Entity(String instrName, long inID, int inintLocX, int inintLocY, int inImage, int inStep, int inintType) {
+ strName = instrName;
+ ID = inID;
+ locx = inintLocX;
+ locy = inintLocY;
+ intImage = inImage;
+ intStep = inStep;
+ intType = inintType;
+ }
+
+ public Entity(ServerMessage.EntityMessage msg) {
+ strName = msg.name;
+ locx = msg.x;
+ locy = msg.y;
+ ID = msg.id;
+ intType = msg.entityType;
+ intImage = msg.image;
+ intStep = msg.imageStep;
+ }
+
+ /**
+ * Returns name without status attributes
+ *
+ * @return
+ */
+ public String getSimpleName() {
+ int i = strName.lastIndexOf(">");
+ if (i != -1) {
+ return strName.substring(i + 1);
+ } else {
+ return strName;
+ }
+ }
+
+ public String getIndexedName() {
+ return intNum == 0 ? strName : intNum + "." + strName;
+ }
+
+ @Override
+ public String toString() {
+
+ return "[Entity " + ID + ", " + strName + ", " + locx + ", " + locy + "]";
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Changes
+ */
+package duskz.client;
+
+import duskz.protocol.Wearing;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * This is a bit junk.
+ * Server code also has a similar mess
+ *
+ * @author notzed
+ */
+public class Equipment implements Wearing {
+
+ /**
+ * Worn items
+ */
+ public String[] worn = new String[WEARING_COUNT];
+ /**
+ * Available items for wearing
+ */
+ public List<String>[] available = new List[WEARING_COUNT];
+ /**
+ * All items
+ */
+ public List<String> all = new ArrayList<>();
+ /**
+ * Where is item wearable at?
+ * FIXME: maybe i should just store them in a structure
+ */
+ HashMap<String, Integer> wearableAt = new HashMap<>();
+
+ public Equipment() {
+ for (int i = 0; i < available.length; i++)
+ available[i] = new ArrayList<>();
+ }
+
+ public int canWearAt(String what) {
+ Integer i = wearableAt.get(what);
+
+ if (i == null)
+ return -1;
+ return i;
+ }
+
+ /**
+ * Returns where what is worn at, if at all.
+ *
+ * @param what
+ * @return -1 if not worn
+ */
+ public int wearingAt(String what) {
+ for (int i = 0; i < worn.length; i++)
+ if (worn[i].equals(what))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Decode worn from network
+ *
+ * @return
+ */
+ public void updateWorn(DataInputStream instream) throws IOException {
+ for (int i = 0; i < worn.length; i++) {
+ worn[i] = instream.readLine();
+ System.out.println(" worn: " + worn[i]);
+ }
+ }
+
+ public void updateAvailable(DataInputStream instream) throws IOException, NumberFormatException {
+ String line;
+
+ all.clear();
+ for (int i = 0; i < available.length; i++)
+ available[i].clear();
+ wearableAt.clear();
+
+ while ((line = instream.readLine()) != null && !line.equals(".")) {
+ // Need to map from server 'id' to our index
+ int i = Integer.parseInt(line) - 1;
+ String s = instream.readLine();
+
+ System.out.println(" " + i + " " + s);
+
+ if (i >= 0 && i < available.length) {
+ available[i].add(s);
+ wearableAt.put(s, i);
+ }
+ all.add(s);
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Changes
+ */
+package duskz.client;
+
+import java.util.List;
+
+/**
+ * Interface for all gui interactions.
+ *
+ * To implement a different frontend toolkit, simply pass this to the Dusk
+ * constructor.
+ *
+ * @author notzed
+ */
+public interface GUI {
+
+ /**
+ * Init, should be called before anything else
+ */
+ public void setGame(Dusk aThis);
+
+ /**
+ * Clear output log, i.e. start of game
+ */
+ public void logClear();
+
+ /**
+ * Log something to the log window
+ *
+ * @param txt
+ */
+ public GUI log(String txt, Object... args);
+ // Init/login
+
+ public void showLogin();
+
+ public void loginOk();
+
+ public void chooseRace(String prompt, List<String> races);
+
+ /**
+ * Show the shop window
+ *
+ * @param title
+ * @param buyList
+ * @param sellList
+ */
+ public void enterShop(String title, List<TransactionItem> buyList, List<TransactionItem> sellList);
+
+ /**
+ * Update the buy list whilst in the shop
+ *
+ * @param buyList
+ */
+ public void setBuyList(List<TransactionItem> buyList);
+
+ /**
+ * Update the sell list whilst in the shop
+ *
+ * @param sellList
+ */
+ public void setSellList(List<TransactionItem> sellList);
+
+ /**
+ * Close the shop window
+ */
+ public void exitShop();
+
+ /**
+ * Open the equipment window
+ *
+ * @param worn
+ */
+ public void manageEquipment(Equipment worn);
+
+ /**
+ * Update the won list, i.e. if in inventory/equipment screen
+ *
+ * @param worn
+ */
+ public void setEquipment(Equipment worn);
+
+ // Misc high level functions
+ public void visitFile(String file, String text, boolean canSave);
+
+ // TODO: parse the content
+ public void setStats(String stats);
+
+ /**
+ * Set hp/mp etc status.
+ *
+ * @param status
+ */
+ public void setStatus(Status status);
+
+ public void setTakeList(List<Entity> list);
+
+ public void setDropList(List<String> list);
+
+ public void setActionList(List<String> list);
+
+ public void setAttackList(List<Entity> list);
+
+ public void setLookList(List<Entity> list);
+
+ // setup/map
+ public void setImages(String tiles, int tileSize, String players, int playerSize, String sprites, int spriteSize);
+
+ /**
+ * Update the map.
+ *
+ * @param map Source map
+ */
+ public void updateMap(ClientMap map);
+
+ /**
+ * Display or log some damage
+ * TODO: use a servermessage for the details
+ * @param e
+ * @param angle angle to attacker
+ * @param locx
+ * @param locy
+ * @param delta how much damage
+ * @param how how it was caused
+ */
+ public void damageEntity(Entity e, double angle, double locx, double locy, int delta, String how);
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - encapsulated a bunch of code out of Dusk
+ * to track the status.
+ */
+package duskz.client;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * Current player information
+ *
+ * @author notzed
+ */
+public class Status {
+
+ long id;
+ // Attack range
+ int range = 1;
+ int hp, maxhp;
+ int mp, maxmp;
+ int locx, locy;
+
+ public void updateStatus(DataInputStream instream) throws IOException {
+ hp = Integer.parseInt(instream.readLine());
+ maxhp = Integer.parseInt(instream.readLine());
+ mp = Integer.parseInt(instream.readLine());
+ maxmp = Integer.parseInt(instream.readLine());
+ }
+
+ public void updateLocation(int x, int y) {
+ locx = x;
+ locy = y;
+ }
+
+ public void updateLocation(DataInputStream instream) throws IOException {
+ //locx = Integer.parseInt(instream.readLine());
+ //locy = Integer.parseInt(instream.readLine());
+ locx = instream.readShort();
+ locy = instream.readShort();
+ }
+
+ @Override
+ public String toString() {
+ return "HP: " + hp + "/" + maxhp + " MP: " + mp + "/" + maxmp + " Loc: " + locx + "/" + locy;
+ }
+
+ public int distance(Entity e) {
+ return Math.abs(locx - e.locx) + Math.abs(locy - e.locy);
+ }
+
+ public boolean canLook(Entity e) {
+ return true;
+ }
+
+ public boolean canTake(Entity e) {
+ return e.intType == 1
+ && (distance(e) < 2);
+ }
+
+ public boolean canAttack(Entity e) {
+ return e.ID != id
+ && ((e.intType == 0 || e.intType == 1 || e.intType == 4)
+ && (distance(e) <= range));
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ. If not, see <http://www.gnu.org/licenses/>.
+ */
+package duskz.client;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Takes a server response and parses it into a name/cost/count
+ * list suitable for a toolkit.
+ *
+ * @deprecated should be merged with DuskCommon's TransactionItem
+ * @author notzed
+ */
+@Deprecated
+public class TransactionItem implements Comparable<TransactionItem> {
+
+ public String cost;
+ public int count;
+ public String name;
+
+ /**
+ * Convert a list of items as from the server into a list of
+ * transaction items.
+ * i.e. count them up, separate cost.
+ *
+ * @param source
+ * @return
+ */
+ public static List<TransactionItem> createItems(List<String> source) {
+ List<TransactionItem> list = new ArrayList<>();
+
+ Collections.sort(source);
+ TransactionItem last = null;
+ String lastName = null;
+ for (String s : source) {
+ if (lastName != null && lastName.equals(s)) {
+ last.count++;
+ } else {
+ int i;
+
+ last = new TransactionItem();
+ last.count = 1;
+
+ i = s.indexOf(')');
+ if (i != -1) {
+ last.cost = s.substring(0, i);
+ last.name = s.substring(i + 1);
+ } else {
+ last.name = s;
+ last.cost = "";
+ }
+ list.add(last);
+ }
+ lastName = s;
+ }
+ Collections.sort(list);
+ return list;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public String getCost() {
+ return cost;
+ }
+
+ @Override
+ public String toString() {
+ return cost + ") " + name + "[" + count + "]";
+ }
+
+ @Override
+ public int compareTo(TransactionItem t) {
+ return name.compareTo(t.name);
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Changes
+ */
+package duskz.client.fx;
+
+import duskz.client.DataManager;
+import java.io.IOException;
+import java.io.InputStream;
+import javafx.geometry.Rectangle2D;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+
+/**
+ * Data manager for JavaFX - loads images into Image nodes and helpers
+ * to create positioned tiles.
+ *
+ * @author notzed
+ */
+public class DataManagerFX extends DataManager {
+
+ public DataManagerFX(String source) {
+ super(source);
+ }
+
+ @Override
+ protected ImageSet createImageSet() {
+ return new ImageSetFX();
+ }
+
+ /**
+ * Create a tile image and align it to the baseline of the map tile.
+ *
+ * This assumes the tiles are the same width but height may vary
+ *
+ * @param tileid
+ * @param tilex
+ * @param tiley
+ * @param tilewidth
+ * @param tileheight
+ * @return
+ */
+ public ImageView createTile(int tileid, int tilex, int tiley, int tilewidth, int tileheight) {
+ try {
+ for (int i = 0; i < tilesets.length; i++) {
+ ImageSetFX is = (ImageSetFX) tilesets[i];
+ if (tileid >= is.gid && tileid < is.gid + is.count) {
+ ImageView iv = new ImageView(is.image);
+
+ tileid -= is.gid;
+ iv.setViewport(new Rectangle2D(tileid * is.width, 0, is.width, is.height));
+ iv.relocate(tilex * tilewidth, tiley * tileheight - (is.height - tileheight));
+
+ return iv;
+ }
+ }
+ } catch (Exception x) {
+ x.printStackTrace();
+ }
+ System.out.println("No such tile: " + tileid);
+ // Broken image?
+ return new ImageView();
+ }
+
+ public class ImageSetFX extends ImageSet {
+
+ Image image;
+
+ public ImageSetFX() {
+ }
+
+ public void load() throws IOException {
+ System.out.println("Load tileset " + name + " gid " + gid + " count " + count);
+ try (InputStream s = getInputStream()) {
+ image = new Image(s);
+ }
+ }
+
+ public Image getImage() {
+ return image;
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Changes
+ */
+package duskz.client.fx;
+
+import duskz.client.Dusk;
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.input.KeyCode;
+import javafx.scene.input.KeyCodeCombination;
+import javafx.stage.Stage;
+
+/**
+ * Main application entry point for JavaFX frontend
+ *
+ * @author notzed
+ */
+public class DuskFX extends Application {
+
+ MainFrameFX frame;
+ Scene scene;
+ Dusk game;
+
+ @Override
+ public void start(Stage stage) {
+ frame = new MainFrameFX();
+ game = new Dusk(frame);
+
+ scene = new Scene(frame);
+ stage.setScene(scene);
+
+ scene.getAccelerators().put(new KeyCodeCombination(KeyCode.ESCAPE), new Runnable() {
+ @Override
+ public void run() {
+ frame.exitWindow();
+ }
+ });
+
+ stage.getScene().getStylesheets().add(DuskFX.class.getResource("style.css").toExternalForm());
+ stage.setTitle("DuskZ JavaFX");
+ stage.show();
+
+ game.startUp();
+ }
+
+ @Override
+ public void stop() throws Exception {
+ game.quit();
+ super.stop();
+ }
+
+ /**
+ * The main() method is ignored in correctly deployed JavaFX application.
+ *
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ launch(args);
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Changes
+ */
+package duskz.client.fx;
+
+import duskz.client.Equipment;
+import java.util.ArrayList;
+import java.util.List;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.ListView;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+import jfxtras.labs.scene.control.ListSpinner;
+
+/**
+ * Pane for a list of equipment with detail area and controls.
+ *
+ * @author notzed
+ */
+public class EquipmentPane extends HBox {
+
+ ListView<ItemInfo> list;
+ Label detail;
+ ListSpinner quantity;
+ Button wear, unwear, drop;
+ Equipment worn;
+
+ public EquipmentPane() {
+ setId("equipment-pane");
+
+ VBox right = new VBox();
+
+ HBox.setHgrow(right, Priority.ALWAYS);
+
+ right.setAlignment(Pos.TOP_RIGHT);
+ right.setFillWidth(true);
+
+ list = new ListView<>();
+ detail = new Label();
+ quantity = new ListSpinner(1, 100);
+
+ HBox hb;
+
+ hb = new HBox();
+ hb.setFillHeight(true);
+ VBox.setVgrow(hb, Priority.ALWAYS);
+ hb.getChildren().add(detail);
+ right.getChildren().add(hb);
+
+ wear = new Button("Wear");
+ unwear = new Button("Un-wear");
+ drop = new Button("Drop");
+
+ wear.setDisable(true);
+ unwear.setDisable(true);
+ drop.setDisable(true);
+
+ hb = new HBox();
+ hb.getChildren().addAll(wear, unwear, drop);
+ hb.setAlignment(Pos.CENTER);
+ right.getChildren().add(hb);
+
+ HBox.setHgrow(list, Priority.NEVER);
+
+ getChildren().addAll(list, right);
+
+ list.setMinWidth(310);
+ list.setMaxWidth(310);
+ list.setEditable(false);
+
+ list.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<ItemInfo>() {
+ @Override
+ public void changed(ObservableValue<? extends ItemInfo> ov, ItemInfo t, ItemInfo t1) {
+ if (t1 != null) {
+ detail.setText(String.format("Item: %s\n\n ... some description or shit ...\n",
+ t1));
+
+ wear.setDisable(t1.wornAt != -1 || worn.canWearAt(t1.name) == -1);
+ unwear.setDisable(t1.wornAt == -1);
+ drop.setDisable(false);
+ } else {
+ detail.setText("");
+ wear.setDisable(true);
+ unwear.setDisable(true);
+ drop.setDisable(true);
+ }
+ }
+ });
+ }
+
+ public ItemInfo getItem() {
+ return list.getSelectionModel().getSelectedItem();
+ }
+
+ static class ItemInfo {
+
+ String name;
+ int wornAt;
+
+ public ItemInfo(String name, int wornAt) {
+ this.name = name;
+ this.wornAt = wornAt;
+ }
+
+ @Override
+ public String toString() {
+ return wornAt == -1 ? name : name + " [worn: " + Equipment.titles[wornAt] + "]";
+ }
+ }
+
+ public void setEquipment(Equipment worn) {
+ this.worn = worn;
+
+ List<ItemInfo> items = new ArrayList<>();
+
+ for (int i = 0; i < worn.worn.length; i++) {
+ String s = worn.worn[i];
+ if (s != null && !s.equals("none"))
+ items.add(new ItemInfo(s, i));
+ }
+ for (String s : worn.all) {
+ items.add(new ItemInfo(s, -1));
+ }
+
+ list.getItems().setAll(items);
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/**
+ * Changes
+ * Feb-2013 Michael Zucchi - This is mostly new apart from
+ * a bit of the keyboard and mouse handler code and the structure of the
+ * rendering pass.
+ */
+package duskz.client.fx;
+
+import duskz.client.Bookmarks;
+import duskz.client.ClientMap;
+import duskz.client.Direction;
+import duskz.client.Dusk;
+import duskz.client.Entity;
+import duskz.client.Equipment;
+import duskz.client.GUI;
+import duskz.client.Status;
+import duskz.client.TransactionItem;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Random;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javafx.animation.FadeTransition;
+import javafx.animation.FadeTransitionBuilder;
+import javafx.animation.Interpolator;
+import javafx.animation.ParallelTransition;
+import javafx.animation.Transition;
+import javafx.animation.TranslateTransitionBuilder;
+import javafx.application.Platform;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.geometry.HPos;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.geometry.Rectangle2D;
+import javafx.geometry.VPos;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.ListView;
+import javafx.scene.control.MenuButton;
+import javafx.scene.control.MenuItem;
+import javafx.scene.control.MenuItemBuilder;
+import javafx.scene.control.PasswordField;
+import javafx.scene.control.Separator;
+import javafx.scene.control.Tab;
+import javafx.scene.control.TabPane;
+import javafx.scene.control.TextArea;
+import javafx.scene.control.TextField;
+import javafx.scene.effect.BoxBlur;
+import javafx.scene.effect.DropShadow;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.KeyCode;
+import static javafx.scene.input.KeyCode.DOWN;
+import static javafx.scene.input.KeyCode.LEFT;
+import static javafx.scene.input.KeyCode.RIGHT;
+import static javafx.scene.input.KeyCode.UP;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Pane;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.StackPane;
+import javafx.scene.layout.VBox;
+import javafx.scene.paint.Color;
+import javafx.scene.shape.Rectangle;
+import javafx.scene.text.Text;
+import javafx.util.Duration;
+
+/**
+ * This is the main JavaFX window.
+ *
+ * It handles all the GUI related operations.
+ *
+ * Prototype code herein, it needs to be split out into functional windows to
+ * make it more manageable
+ *
+ * @author notzed
+ */
+public class MainFrameFX extends StackPane implements GUI {
+
+ Dusk game;
+ //
+ BorderPane main;
+ StackPane layers;
+ Pane graphics;
+ Pane battle;
+ BorderPane panel;
+ VBox buttons;
+ TextArea stats;
+ TextArea log;
+ TextField cmdLine;
+ Label info;
+ // just clone interface to start with
+ MenuButton attack, action, look, get, drop;
+ //
+ Button connect, merchant, equipment, quit;
+ /**
+ * **************
+ * Behaviour state
+ */
+ /**
+ * "!command" allows one to execute a fixed operation after every move.
+ */
+ private String postMove;
+
+ public void setGame(Dusk game) {
+ this.game = game;
+ }
+
+ public MainFrameFX() {
+ layers = new StackPane();
+
+ getChildren().add(main = new BorderPane());
+
+ layers.getChildren().addAll(graphics = new Pane(), battle = new Pane());
+
+ layers.setPrefSize(416, 416);
+ main.setCenter(layers);
+
+ //layers.setScaleX(2);
+ //layers.setScaleY(2);
+
+ panel = new BorderPane();
+ panel.setMaxWidth(320);
+ main.setRight(panel);
+
+ buttons = new VBox();
+ stats = new TextArea();
+ panel.setTop(info = new Label());
+ panel.setLeft(buttons);
+ panel.setCenter(stats);
+
+ buttons.getChildren().addAll(
+ attack = new MenuButton("Attack"),
+ action = new MenuButton("Action"),
+ look = new MenuButton("Look"),
+ get = new MenuButton("Get"),
+ drop = new MenuButton("Drop"),
+ connect = new Button("Connect"),
+ merchant = new Button("Merchant"),
+ equipment = new Button("Equipment"),
+ quit = new Button("Quit"));
+
+ attack.setMaxWidth(Double.MAX_VALUE);
+ action.setMaxWidth(Double.MAX_VALUE);
+ look.setMaxWidth(Double.MAX_VALUE);
+ get.setMaxWidth(Double.MAX_VALUE);
+ drop.setMaxWidth(Double.MAX_VALUE);
+ connect.setMaxWidth(Double.MAX_VALUE);
+ merchant.setMaxWidth(Double.MAX_VALUE);
+ equipment.setMaxWidth(Double.MAX_VALUE);
+ quit.setMaxWidth(Double.MAX_VALUE);
+
+ BorderPane lower = new BorderPane();
+ main.setBottom(lower);
+
+ lower.setTop(cmdLine = new TextField());
+ lower.setBottom(log = new TextArea());
+
+ // Events
+ cmdLine.setOnKeyPressed(keyPressed);
+ layers.setOnKeyPressed(keyPressed);
+ layers.setOnMouseClicked(mouseClicked);
+
+ merchant.setOnAction(new EventHandler<javafx.event.ActionEvent>() {
+ public void handle(javafx.event.ActionEvent t) {
+ game.merchant();
+ }
+ });
+ quit.setOnAction(new EventHandler<javafx.event.ActionEvent>() {
+ public void handle(javafx.event.ActionEvent t) {
+ game.quit();
+ }
+ });
+ equipment.setOnAction(new EventHandler<javafx.event.ActionEvent>() {
+ public void handle(javafx.event.ActionEvent t) {
+ game.equipment();
+ }
+ });
+ connect.setOnAction(new EventHandler<javafx.event.ActionEvent>() {
+ public void handle(javafx.event.ActionEvent t) {
+ //userconnect();
+ }
+ });
+ }
+ Random rand = new Random();
+
+ public void damageEntity(Entity e, double direction, double x, double y, int delta, String what) {
+ final Label node = new Label(String.format("%s %+d", what, delta));
+
+ if (delta <= 0) {
+ node.setId("damage-bubble");
+ } else {
+ node.setId("health-bubble");
+ }
+ node.relocate(x, y);
+
+ Duration dur = Duration.millis(1500);
+ // Fade out
+ Transition fade =
+ FadeTransitionBuilder.create().node(node)
+ .duration(dur)
+ .interpolator(Interpolator.EASE_IN)
+ .fromValue(1)
+ .toValue(0)
+ .onFinished(new EventHandler<ActionEvent>() {
+ @Override
+ public void handle(ActionEvent t) {
+ battle.getChildren().remove(node);
+ }
+ }).build();
+
+ // animate randomly away from centre
+ double a = rand.nextDouble() * Math.PI * 0.75 + direction - Math.PI * 0.375;
+
+ //a = direction;
+
+ double radius = 32;
+ double sx = Math.cos(a) * radius / 2;
+ double sy = Math.sin(a) * radius / 2;
+ double ex = Math.cos(a) * radius + sx;
+ double ey = Math.sin(a) * radius + sy;
+
+ Transition move =
+ TranslateTransitionBuilder.create().node(node)
+ .duration(dur)
+ .interpolator(Interpolator.EASE_OUT)
+ .fromX(sx).fromY(sy)
+ .toX(ex).toY(ey)
+ .build();
+
+ final Transition t = new ParallelTransition(fade, move);
+
+ // Quick and dirty 'damage' popup
+ Platform.runLater(new Runnable() {
+ @Override
+ public void run() {
+ battle.getChildren().add(node);
+
+ t.play();
+ }
+ });
+ }
+ Bookmarks bm;
+ GridPane loginPane;
+ ListView<Bookmarks.Bookmark> marks;
+ TextField host;
+ TextField port;
+ TextField user;
+ TextField pass;
+
+ public void showLogin() {
+ if (loginPane != null) {
+ return;
+ }
+
+ loginPane = new GridPane();
+ loginPane.setId("login-window");
+ loginPane.setPrefSize(320, 200);
+ loginPane.setMaxSize(500, 300);
+ StackPane.setAlignment(loginPane, Pos.CENTER);
+
+ bm = new Bookmarks();
+ try {
+ bm.load("bookmarks");
+ } catch (FileNotFoundException x) {
+ } catch (IOException ex) {
+ Logger.getLogger(MainFrameFX.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ marks = new ListView<>();
+
+ marks.getItems().setAll(bm.getBookmarks());
+ Label l;
+ Insets li = new Insets(4, 8, 4, 8);
+ loginPane.add(marks, 0, 0, 1, 7);
+
+ loginPane.add(l = new Label("Host"), 1, 0);
+ GridPane.setMargin(l, li);
+ loginPane.add(host = new TextField(), 2, 0);
+ loginPane.add(l = new Label("Port"), 1, 1);
+ GridPane.setMargin(l, li);
+ loginPane.add(port = new TextField(), 2, 1);
+
+ GridPane.setHgrow(host, Priority.ALWAYS);
+ GridPane.setHgrow(port, Priority.ALWAYS);
+
+ Separator empty = new Separator();
+ GridPane.setVgrow(empty, Priority.ALWAYS);
+ loginPane.add(empty, 1, 2, 2, 1);
+
+ HBox hbox;
+ loginPane.add(hbox = new HBox(), 1, 3, 2, 1);
+ hbox.setAlignment(Pos.CENTER);
+ //GridPane.setHalignment(hbox, HPos.CENTER);
+ Button add = new Button("Add");
+ Button remove = new Button("Remove");
+
+ hbox.getChildren().addAll(add, remove);
+
+ loginPane.add(l = new Label("User"), 1, 4);
+ GridPane.setMargin(l, li);
+ loginPane.add(user = new TextField(), 2, 4);
+ loginPane.add(l = new Label("Pass"), 1, 5);
+ GridPane.setMargin(l, li);
+ loginPane.add(pass = new PasswordField(), 2, 5);
+
+ Button login = new Button("Connect");
+
+ GridPane.setValignment(login, VPos.BOTTOM);
+ GridPane.setHalignment(login, HPos.CENTER);
+ loginPane.add(login, 1, 6, 2, 1);
+
+
+ GridPane.setVgrow(hbox, Priority.NEVER);
+ GridPane.setVgrow(login, Priority.NEVER);
+
+ bm.setBookmarks(marks.getItems());
+
+ marks.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Bookmarks.Bookmark>() {
+ public void changed(ObservableValue<? extends Bookmarks.Bookmark> ov, Bookmarks.Bookmark t, Bookmarks.Bookmark t1) {
+ host.setText(t1.host);
+ port.setText(Integer.toString(t1.port));
+ }
+ });
+
+ add.setOnAction(new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ try {
+ marks.getItems().add(new Bookmarks.Bookmark(host.getText(), Integer.valueOf(port.getText())));
+ bm.save("bookmarks");
+ } catch (NumberFormatException x) {
+ } catch (IOException x) {
+ }
+ }
+ });
+
+ remove.setOnAction(new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ int i = marks.getSelectionModel().getSelectedIndex();
+ try {
+
+ if (i != -1) {
+ marks.getItems().remove(i);
+ bm.save("bookmarks");
+ }
+ } catch (IOException ex) {
+ Logger.getLogger(MainFrameFX.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ });
+
+ login.setOnAction(new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ System.out.println("logging in!");
+ game.connect(host.getText(), Integer.valueOf(port.getText()), user.getText(), pass.getText());
+ }
+ });
+
+ loginPane.setOpacity(0);
+ getChildren().add(loginPane);
+
+ FadeTransition anim = new FadeTransition(Duration.millis(250), loginPane);
+ anim.setFromValue(0);
+ anim.setToValue(1);
+ anim.play();
+ }
+
+ public void loginFailed() {
+ // display somewhere?
+ }
+
+ public void loginOk() {
+ if (loginPane != null) {
+ closeWindow(loginPane);
+ loginPane = null;
+ }
+ }
+
+ void closeWindow(final Pane window) {
+ Platform.runLater(new Runnable() {
+ public void run() {
+ main.setEffect(null);
+ if (true) {
+ final FadeTransition anim = new FadeTransition(Duration.millis(250), window);
+
+ anim.setFromValue(1);
+ anim.setToValue(0);
+ anim.setOnFinished(new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ getChildren().remove(anim.getNode());
+ }
+ });
+ anim.play();
+ } else {
+ getChildren().remove(window);
+ }
+ }
+ });
+ }
+ GridPane racePane;
+ ListView<String> raceList;
+
+ public void chooseRace(String prompt, List<String> races) {
+ if (racePane != null) {
+ return;
+ }
+
+ racePane = new GridPane();
+ racePane.setId("race-window");
+ racePane.setMaxSize(500, 300);
+ StackPane.setAlignment(racePane, Pos.CENTER);
+
+ raceList = new ListView<>();
+ raceList.getItems().setAll(races);
+
+ racePane.add(new Label(prompt), 0, 0);
+
+ racePane.add(raceList, 0, 1);
+
+ Button ok = new Button("Ok");
+
+ racePane.add(ok, 0, 2);
+
+ ok.setOnAction(new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ String item = raceList.getSelectionModel().getSelectedItem();
+ if (item != null) {
+ getChildren().remove(racePane);
+ racePane = null;
+ game.chooseRace(item);
+ }
+ }
+ });
+
+ Platform.runLater(new Runnable() {
+ public void run() {
+ getChildren().add(racePane);
+ }
+ });
+
+ }
+ /**
+ * Need to know about merchant changes so track them here.
+ */
+ VBox shopPane;
+ TransactionPane buyPane;
+ TransactionPane sellPane;
+
+ public void setBuyList(final List<TransactionItem> buyList) {
+ Platform.runLater(new Runnable() {
+ public void run() {
+ if (shopPane != null) {
+ buyPane.setItems(buyList);
+ }
+ merchant.setDisable(false);
+ }
+ });
+ }
+
+ public void setSellList(final List<TransactionItem> sellList) {
+ Platform.runLater(new Runnable() {
+ public void run() {
+ if (shopPane != null) {
+ sellPane.setItems(sellList);
+ }
+ merchant.setDisable(false);
+ }
+ });
+ }
+
+ @Override
+ public void exitShop() {
+ merchant.setDisable(!false);
+ if (shopPane != null) {
+ closeWindow(shopPane);
+ shopPane = null;
+ }
+ }
+
+ @Override
+ public void enterShop(String title, final List<TransactionItem> buyList, final List<TransactionItem> sellList) {
+ if (shopPane != null) {
+ // update items?
+ Platform.runLater(new Runnable() {
+ public void run() {
+ buyPane.setItems(buyList);
+ sellPane.setItems(sellList);
+ }
+ });
+
+ return;
+ }
+
+ shopPane = new VBox();
+ shopPane.setId("shop-window");
+ shopPane.setMaxSize(600, 400);
+ StackPane.setAlignment(shopPane, Pos.CENTER);
+
+ TabPane tabs = new TabPane();
+
+ Tab tab = new Tab("Buy");
+ Button b;
+
+ buyPane = new TransactionPane(b = new Button("Buy"));
+ tab.setContent(buyPane);
+ tab.setClosable(false);
+ tabs.getTabs().add(tab);
+
+ b.setOnAction(new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ game.buy(buyPane.getItem(), buyPane.getQuantity());
+ }
+ });
+
+ tab = new Tab("Sell");
+ sellPane = new TransactionPane(b = new Button("Sell"));
+ tab.setContent(sellPane);
+ tab.setClosable(false);
+ tabs.getTabs().add(tab);
+
+ b.setOnAction(new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ game.sell(sellPane.getItem(), sellPane.getQuantity());
+ }
+ });
+
+ Label head = new Label(title);
+ head.setId("window-title");
+ head.setAlignment(Pos.BASELINE_LEFT);
+
+ buyPane.setItems(buyList);
+ sellPane.setItems(sellList);
+
+ Button tail = new Button("Leave");
+
+ tail.setOnAction(new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ closeWindow(shopPane);
+ shopPane = null;
+ }
+ });
+
+ shopPane.setAlignment(Pos.CENTER);
+ shopPane.getChildren().addAll(head, tabs, tail);
+
+ Platform.runLater(new Runnable() {
+ public void run() {
+ main.setEffect(new BoxBlur(3, 3, 2));
+ getChildren().add(shopPane);
+ }
+ });
+ }
+ VBox equipWindow;
+ EquipmentPane equip;
+
+ @Override
+ public void manageEquipment(Equipment worn) {
+ if (equipWindow != null) {
+ equip.setEquipment(worn);
+ return;
+ }
+
+ equipWindow = new VBox();
+ equipWindow.setId("shop-window");
+ equipWindow.setMaxSize(600, 400);
+ StackPane.setAlignment(equipWindow, Pos.CENTER);
+
+ equip = new EquipmentPane();
+
+ Label head = new Label("Equipment");
+ head.setId("window-title");
+ head.setAlignment(Pos.BASELINE_LEFT);
+
+ equip.setEquipment(worn);
+
+ Button tail = new Button("Return");
+
+ tail.setOnAction(new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ closeWindow(equipWindow);
+ equipWindow = null;
+ }
+ });
+
+ equipWindow.setAlignment(Pos.CENTER);
+ equipWindow.getChildren().addAll(head, equip, tail);
+
+ equip.wear.setOnAction(new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ game.wear(equip.getItem().name);
+ }
+ });
+ equip.unwear.setOnAction(new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ EquipmentPane.ItemInfo ii = equip.getItem();
+ game.unwear(Equipment.names[ii.wornAt]);
+ }
+ });
+ equip.drop.setOnAction(new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ game.drop(equip.getItem().name);
+ }
+ });
+
+ Platform.runLater(new Runnable() {
+ public void run() {
+ main.setEffect(new BoxBlur(3, 3, 2));
+ getChildren().add(equipWindow);
+ }
+ });
+
+
+ }
+
+ /**
+ * For closing poup windows that can be closed
+ */
+ public void exitWindow() {
+ if (shopPane != null) {
+ closeWindow(shopPane);
+ shopPane = null;
+ }
+ }
+
+ @Override
+ public void visitFile(String file, String text, boolean canSave) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ // FIXME: implement edit text,
+ // FIXME: sent using: appParent.outstream.writeBytes("submit "+strName+"\n");
+ // appParent.outstream.writeBytes(txtEdit.getText()+"\n--EOF--\n");
+ }
+ //Accept key input
+ EventHandler<javafx.scene.input.KeyEvent> keyPressed = new EventHandler<javafx.scene.input.KeyEvent>() {
+ @Override
+ public void handle(javafx.scene.input.KeyEvent evt) {
+ if (!game.isConnected()) {
+ return;
+ }
+
+ KeyCode nkey = evt.getCode();
+ if (nkey == KeyCode.ENTER) {
+ String cmd = cmdLine.getText();
+ //Thanks to Joe Alloway for this addition
+ if (cmd.startsWith("!")) {
+ if (cmd.length() == 1) {
+ postMove = null;
+ } else {
+ postMove = cmd.substring(1);
+ }
+ } else {
+ game.command(cmd);
+ }
+ //End contribution by Joe Alloway
+ cmdLine.setText("");
+ }
+ if (game.isLoaded()) {
+ Direction dir = null;
+ switch (nkey) {
+ case UP:
+ dir = Direction.North;
+ break;
+ case DOWN:
+ dir = Direction.South;
+ break;
+ case LEFT:
+ dir = Direction.West;
+ break;
+ case RIGHT:
+ dir = Direction.East;
+ break;
+ }
+ if (dir != null) {
+ game.move(dir);
+ if (postMove != null)
+ game.command(postMove);
+ }
+ }
+ }
+ };
+ EventHandler<javafx.scene.input.MouseEvent> mouseClicked = new EventHandler<javafx.scene.input.MouseEvent>() {
+ @Override
+ public void handle(javafx.scene.input.MouseEvent evt) {
+ System.out.println("Mouse clicked: " + evt);
+ if (!game.isConnected() || !game.isLoaded()) {
+ return;
+ }
+
+ /**
+ * Map coordinates to screen-relative tiles and pass to game.
+ */
+ int x = (int) evt.getX();
+ int y = (int) evt.getY();
+ int destX = (x / game.getTileSize()) + game.getMapOffsetX();
+ int destY = (y / game.getTileSize()) + game.getMapOffsetY();
+
+ game.moveTo(destX, destY);
+ cmdLine.requestFocus();
+ }
+ };
+ EventHandler<ActionEvent> attackHandler = new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ game.attack((Entity) ((MenuItem) t.getSource()).getUserData());
+ }
+ };
+ EventHandler<ActionEvent> lookHandler = new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ game.look((Entity) ((MenuItem) t.getSource()).getUserData());
+ }
+ };
+ EventHandler<ActionEvent> actionHandler = new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ MenuItem mi = (MenuItem) t.getSource();
+ game.command(mi.getText());
+ }
+ };
+ EventHandler<ActionEvent> getHandler = new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ game.take((Entity) ((MenuItem) t.getSource()).getUserData());
+ }
+ };
+ EventHandler<ActionEvent> dropHandler = new EventHandler<ActionEvent>() {
+ public void handle(ActionEvent t) {
+ game.drop(((MenuItem) t.getSource()).getText());
+ }
+ };
+
+ @Override
+ public void logClear() {
+ Platform.runLater(new Runnable() {
+ public void run() {
+ log.setText("");
+ }
+ });
+ }
+
+ @Override
+ public GUI log(String txt, Object... args) {
+ final String s = String.format(txt, args);
+
+ Platform.runLater(new Runnable() {
+ public void run() {
+
+ // Truncate history
+ if (log.textProperty().getValueSafe().length() > 8000) {
+ log.deleteText(0, 4000);
+ }
+
+ log.appendText(s);
+ }
+ });
+ return this;
+ }
+
+ void setStringMenu(final MenuButton menu, List<String> list, EventHandler<ActionEvent> handle) {
+ final List<MenuItem> items = new ArrayList<>();
+ MenuItemBuilder mib = MenuItemBuilder.create().onAction(handle);
+
+ for (String e : list) {
+ items.add(mib.text(e).build());
+ }
+ Platform.runLater(new Runnable() {
+ @Override
+ public void run() {
+ menu.getItems().setAll(items);
+ }
+ });
+ }
+
+ void setEntityMenu(final MenuButton menu, List<Entity> list, EventHandler<ActionEvent> handle) {
+ final List<MenuItem> items = new ArrayList<>();
+ MenuItemBuilder mib = MenuItemBuilder.create().onAction(handle);
+
+ for (Entity e : list) {
+ items.add(mib.userData(e).text(e.getIndexedName()).build());
+ }
+ Platform.runLater(new Runnable() {
+ public void run() {
+ menu.getItems().setAll(items);
+ }
+ });
+ }
+
+ @Override
+ public void setDropList(List<String> drops) {
+ setStringMenu(drop, drops, dropHandler);
+ }
+
+ @Override
+ public void setAttackList(List<Entity> list) {
+ setEntityMenu(attack, list, attackHandler);
+ }
+
+ @Override
+ public void setTakeList(List<Entity> list) {
+ setEntityMenu(get, list, getHandler);
+ }
+
+ @Override
+ public void setLookList(List<Entity> list) {
+ setEntityMenu(look, list, lookHandler);
+ }
+
+ @Override
+ public void setActionList(List<String> list) {
+ setStringMenu(action, list, actionHandler);
+ }
+
+ @Override
+ public void setStats(final String stats) {
+ Platform.runLater(new Runnable() {
+ public void run() {
+ MainFrameFX.this.stats.setText(stats);
+ }
+ });
+ }
+
+ @Override
+ public void setStatus(final Status status) {
+ Platform.runLater(new Runnable() {
+ public void run() {
+ info.setText(status.toString());
+ }
+ });
+ }
+
+ @Override
+ public void setEquipment(final Equipment worn) {
+ Platform.runLater(new Runnable() {
+ public void run() {
+ if (equipWindow != null) {
+ equip.setEquipment(worn);
+ }
+ }
+ });
+ }
+ //DataManagerFX data;
+ Image tileImage;
+ int tileSize;
+ Image playerImage;
+ int playerSize;
+ Image spriteImage;
+ int spriteSize;
+
+ @Override
+ public void setImages(String tiles, int tileSize, String players, int playerSize, String sprites, int spriteSize) {
+ //try {
+ System.out.println("set tile image");
+ // FIXME: put sprites into data manager
+ //data = new DataManagerFX("/home/notzed/house.jar");
+ //data.open();
+ tileImage = new Image(tiles, false);
+ this.tileSize = tileSize;
+ playerImage = new Image(players, false);
+ this.playerSize = playerSize;
+ spriteImage = new Image(sprites, false);
+ this.spriteSize = spriteSize;
+ //} catch (IOException ex) {
+ // Logger.getLogger(MainFrameFX.class.getName()).log(Level.SEVERE, null, ex);
+ //}
+ }
+
+ @Override
+ public void updateMap(ClientMap map) {
+ // First ugly cut - just create a whole set of tiles
+ System.out.println("update map");
+ //if (data == null) {
+ if (tileImage == null) {
+ System.out.println("Map not ready yet");
+ return;
+ }
+
+ final ArrayList<Node> children = new ArrayList<>();
+ final ArrayList<Node> upper = new ArrayList<>();
+
+ // Build map
+ for (int y = 0; y < map.rows; y++) {
+ for (int x = 0; x < map.cols; x++) {
+ ImageView iv = new ImageView(tileImage);
+ int tileid = map.getTile(x, y);
+ iv.setViewport(new Rectangle2D(tileid * tileSize, 0, tileSize, tileSize));
+ iv.relocate(x * tileSize, y * tileSize);
+ children.add(iv);
+
+ //children.add(data.createTile(map.getTile(x, y), x, y, tileSize, tileSize));
+
+ // TODO: names always? on top
+ Collection<Entity> ents = map.getEntities(x + map.offx, y + map.offy);
+ if (ents != null) {
+ for (Entity e : ents) {
+ drawEntity(e, map.offx, map.offy, children, upper);
+ }
+ }
+ }
+ }
+
+ // Build sprites
+ //for (Entity e : map.getEntities()) {
+ // drawEntity(map.offx, map.offy, children, e);
+ //}
+
+ Platform.runLater(new Runnable() {
+ @Override
+ public void run() {
+ graphics.getChildren().setAll(children);
+ graphics.getChildren().addAll(upper);
+ }
+ });
+ }
+ DropShadow textShadow = new DropShadow(3, 2, 2, Color.BLACK);
+
+ // HACK: upper is used for 'upper layer', stuff drawn afterwards
+ void drawEntity(Entity e, int offx, int offy, ArrayList<Node> children, ArrayList<Node> upper) {
+ double x = e.locx - offx;
+ double y = e.locy - offy;
+
+ // TODO: just make it an entity node
+
+ if (e.intStep == -1) {
+ // Hack: sprites are 64x64
+ ImageView iv = new ImageView(spriteImage);
+ iv.setViewport(new Rectangle2D(e.intImage * spriteSize, 0,
+ spriteSize, spriteSize));
+ iv.relocate((x * tileSize) - tileSize / 2, (y * tileSize) - tileSize / 2);
+ iv.setScaleX(0.5);
+ iv.setScaleY(0.5);
+ children.add(iv);
+
+ } else {
+ ImageView iv = new ImageView(playerImage);
+ iv.setViewport(new Rectangle2D((e.intImage * 8 + e.intStep) * spriteSize, 0,
+ spriteSize, spriteSize));
+ iv.relocate((x * tileSize) - tileSize / 2, (y * tileSize) - tileSize / 2);
+ iv.setScaleX(0.5);
+ iv.setScaleY(0.5);
+ children.add(iv);
+ }
+ if (e.intNum == 0) {
+ Text t = new Text(e.strName);
+ t.setId("entity-label");
+ t.relocate((x * tileSize) + tileSize / 2 - t.getLayoutBounds().getWidth() / 2, ((y + 1) * tileSize));
+ upper.add(t);
+ } else {
+ Text t = new Text(e.intNum + "." + e.strName);
+ t.setId("entity-label");
+ t.relocate((x * tileSize) + tileSize / 2 - t.getLayoutBounds().getWidth() / 2, ((y + 1) * tileSize));
+ upper.add(t);
+ }
+ //Draw flag
+ if (e.intFlag != 0) {
+ Rectangle r = new Rectangle(1, 1, tileSize - 2, tileSize - 2);
+ if (e.intFlag == 1) {
+ r.setStroke(Color.GREEN);
+ } else if (e.intFlag == 2) {
+ r.setStroke(Color.RED);
+ }
+ r.setStrokeWidth(2);
+ r.setArcHeight(12);
+ r.setArcWidth(12);
+ r.setFill(null);
+ r.relocate(x * tileSize, y * tileSize);
+ upper.add(r);
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * DuskZ is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DuskZ 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DuskZ. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Changes
+ */
+package duskz.client.fx;
+
+import duskz.client.TransactionItem;
+import java.util.List;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.cell.PropertyValueFactory;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+import jfxtras.labs.scene.control.ListSpinner;
+
+/**
+ *
+ * @author notzed
+ */
+public class TransactionPane extends HBox {
+
+ TableView<TransactionItem> table;
+ Label detail;
+ ListSpinner quantity;
+ Button action;
+
+ public TransactionPane(Button action) {
+ this.action = action;
+
+ setId("buy-pane");
+
+ VBox right = new VBox();
+
+ HBox.setHgrow(right, Priority.ALWAYS);
+
+ right.setAlignment(Pos.TOP_RIGHT);
+ right.setFillWidth(true);
+
+ table = new TableView<>();
+ detail = new Label();
+ quantity = new ListSpinner(1, 100);
+
+ HBox hb;
+
+ hb = new HBox();
+ hb.setFillHeight(true);
+ VBox.setVgrow(hb, Priority.ALWAYS);
+ hb.getChildren().add(detail);
+ right.getChildren().add(hb);
+
+ hb = new HBox();
+ hb.getChildren().add(quantity);
+ hb.getChildren().add(new Label("Quantity:"));
+ hb.setAlignment(Pos.CENTER);
+ right.getChildren().add(hb);
+
+ // hb = new HBox();
+ // hb.getChildren().add(action);
+ // hb.setAlignment(Pos.BOTTOM_RIGHT);
+ // right.getChildren().add(hb);
+ right.getChildren().add(action);
+
+ HBox.setHgrow(table, Priority.NEVER);
+
+ getChildren().addAll(table, right);
+
+
+ TableColumn<TransactionItem, String> countCol = new TableColumn<TransactionItem, String>("Count");
+ countCol.setCellValueFactory(new PropertyValueFactory("count"));
+
+ TableColumn<TransactionItem, String> nameCol = new TableColumn<TransactionItem, String>("Name");
+ nameCol.setCellValueFactory(new PropertyValueFactory("name"));
+
+ TableColumn<TransactionItem, String> costCol = new TableColumn<TransactionItem, String>("Cost");
+ costCol.setCellValueFactory(new PropertyValueFactory("cost"));
+
+ table.getColumns().setAll(countCol, nameCol, costCol);
+
+ countCol.setMinWidth(50);
+ nameCol.setMinWidth(180);
+ costCol.setMinWidth(50);
+ table.setMinWidth(310);
+ table.setMaxWidth(310);
+
+ countCol.setResizable(false);
+ nameCol.setResizable(false);
+ costCol.setResizable(false);
+ table.setEditable(false);
+
+ table.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TransactionItem>() {
+ @Override
+ public void changed(ObservableValue<? extends TransactionItem> ov, TransactionItem t, TransactionItem t1) {
+ if (t1 != null) {
+ detail.setText(String.format("Item: %s\nCost: %s\n\n ... some description or shit ...\n",
+ t1.name, t1.cost));
+ } else {
+ detail.setText("");
+ }
+ }
+ });
+ }
+
+ public int getQuantity() {
+ return ((Number) quantity.getValue()).intValue();
+ }
+
+ public TransactionItem getItem() {
+ return table.getSelectionModel().getSelectedItem();
+ }
+
+ public void setItems(List<TransactionItem> items) {
+ this.table.getItems().setAll(items);
+ }
+}
--- /dev/null
+/*
+ Document : style
+ Created on : 21/02/2013, 11:27:00 AM
+ Author : notzed
+ Description: A very ugly stylesheet just waiting for a graphical designer
+ to improve it.
+*/
+
+.scene {
+ /* global palette */
+ enitity-background: rgba(1,1,0.5,0.25);
+}
+.button {
+ -fx-background-color:
+ #c3c4c4,
+ linear-gradient(#d6d6d6 50%, white 100%),
+ radial-gradient(center 50% -40%, radius 200%, #e6e6e6 45%, rgba(230,230,230,0) 50%);
+ /* -fx-background-radius: 30;*/
+ -fx-background-insets: 0,1,1;
+ -fx-text-fill: black;
+ -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 3, 0.0 , 0 , 1 );
+}
+
+#login-window, #race-window, #shop-window {
+ -fx-padding: 10;
+ -fx-border-color: #000000;
+ -fx-border-radius: 12;
+ -fx-background-radius: 12;
+ -fx-background-color:
+ linear-gradient(to bottom right, antiquewhite, maroon);
+}
+
+#entity-label {
+ -fx-font-family: 'sans';
+ -fx-font-size: small;
+ -fx-font-weight: bold;
+ -fx-fill: white;
+ -fx-effect: dropshadow(one-pass-box, black, 4, 0, 2, 2);
+}
+#window-title {
+ -fx-font-family: 'serif';
+ -fx-font-size: x-large;
+}
+.tab-pane {
+ -fx-tab-min-width: 250px;
+}
+
+.tab-header-area {
+ -fx-alignment: center;
+}
+
+#shop-window .table-view {
+ -fx-padding: 5px;
+}
+#shop-window .table-cell {
+ -fx-font-size: small;
+ -fx-padding: 0px;
+}
+
+.table-row-cell, .list-cell {
+ -fx-background-color: lemonchiffon;
+}
+.table-row-cell:selected, .list-cell:selected {
+ -fx-background-color: burlywood;
+}
+#shop-window .label {
+ -fx-padding: 5px;
+}
+#health-bubble, #damage-bubble {
+ -fx-background-radius: 20;
+ -fx-background-insets: 0;
+ -fx-text-fill: black;
+ -fx-padding: 4;
+}
+
+#health-bubble {
+ -fx-background-color: #33c333,
+ linear-gradient(#33c333 50%, white 100%),
+ radial-gradient(center 50% -40%, radius 200%, #e6e6e6 45%, rgba(230,230,230,0) 50%);
+}
+#damage-bubble {
+ -fx-background-color: #c33333,
+ linear-gradient(#c33333 50%, white 100%),
+ radial-gradient(center 50% -40%, radius 200%, #e6e6e6 45%, rgba(230,230,230,0) 50%);
+}
--- /dev/null
+/**
+ * Copyright (c) 2011, JFXtras
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jfxtras.labs.animation;
+
+import java.util.TimerTask;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javafx.application.Platform;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.util.Duration;
+
+/**
+ * A timer class in the spirit of java.swing.Timer but using JavaFX properties.
+ *
+ * @author Tom Eugelink
+ *
+ */
+public class Timer
+{
+ // ==================================================================================================================
+ // CONSTRUCTOR
+
+ /**
+ *
+ * @param runnable
+ */
+ public Timer(Runnable runnable)
+ {
+ this(true, runnable);
+ }
+
+ /**
+ *
+ * @param isDaemon
+ * @param runnable
+ */
+ public Timer(boolean isDaemon, final Runnable runnable)
+ {
+ this.runnable = runnable;
+ timer = new java.util.Timer(isDaemon);
+ }
+ final private Runnable runnable;
+ final private java.util.Timer timer;
+
+ // ==================================================================================================================
+ // PROPERTIES
+
+ /** delay: initial delay */
+ public ObjectProperty<Duration> delayProperty() { return this.delayObjectProperty; }
+ final private ObjectProperty<Duration> delayObjectProperty = new SimpleObjectProperty<Duration>(this, "delay", Duration.millis(0));
+ public Duration getDelay() { return this.delayObjectProperty.getValue(); }
+ public void setDelay(Duration value) { this.delayObjectProperty.setValue(value); }
+ public Timer withDelay(Duration value) { setDelay(value); return this; }
+
+ /** cycleDuration: time between fires */
+ public ObjectProperty<Duration> cycleDurationProperty() { return this.cycleDurationObjectProperty; }
+ final private ObjectProperty<Duration> cycleDurationObjectProperty = new SimpleObjectProperty<Duration>(this, "cycleDuration", Duration.millis(1000));
+ public Duration getCycleDuration() { return this.cycleDurationObjectProperty.getValue(); }
+ public void setCycleDuration(Duration value) { this.cycleDurationObjectProperty.setValue(value); }
+ public Timer withCycleDuration(Duration value) { setCycleDuration(value); return this; }
+
+ /** repeats: If flag is false, instructs the Timer to send only one action event to its listeners. */
+ public ObjectProperty<Boolean> repeatsProperty() { return this.repeatsObjectProperty; }
+ final private ObjectProperty<Boolean> repeatsObjectProperty = new SimpleObjectProperty<Boolean>(this, "repeats", Boolean.TRUE);
+ public boolean getRepeats() { return this.repeatsObjectProperty.getValue(); }
+ public void setRepeats(boolean value) { this.repeatsObjectProperty.setValue(value); }
+ public Timer withRepeats(boolean value) { setRepeats(value); return this; }
+
+
+ // ==================================================================================================================
+ // TIMER
+
+ /**
+ * Start the timer
+ */
+ synchronized public Timer start()
+ {
+ // check if the timer is already running
+ if (timerTaskAtomicReference.get() != null) throw new IllegalStateException("Timer already started");
+
+ // create a task and schedule it
+ final TimerTask lTimerTask = new TimerTask()
+ {
+ @Override
+ public void run()
+ {
+ Platform.runLater(runnable);
+ if (repeatsObjectProperty.getValue().booleanValue() == false)
+ {
+ stop();
+ }
+ }
+ };
+ timer.schedule(lTimerTask, (long)this.delayObjectProperty.getValue().toMillis(), (long)this.cycleDurationObjectProperty.getValue().toMillis());
+
+ // remember for future reference
+ timerTaskAtomicReference.set(lTimerTask);
+
+ // for chaining
+ return this;
+ }
+ final private AtomicReference<TimerTask> timerTaskAtomicReference = new AtomicReference<TimerTask>(null);
+
+ /**
+ * stop the timer if running
+ */
+ public Timer stop()
+ {
+ TimerTask lTimerTask = timerTaskAtomicReference.getAndSet(null);
+ if (lTimerTask != null)
+ {
+ lTimerTask.cancel();
+ }
+
+ // for chaining
+ return this;
+ }
+
+ /**
+ * restart the timer
+ */
+ public Timer restart()
+ {
+ stop();
+ start();
+
+ // for chaining
+ return this;
+ }
+}
--- /dev/null
+/* basic settings */\r
+.ListSpinner { \r
+ -fx-skin: "jfxtras.labs.internal.scene.control.skin.ListSpinnerCaspianSkin";\r
+ -fx-background-color: -fx-shadow-highlight-color, -fx-outer-border, -fx-inner-border, -fx-body-color;\r
+ -fx-background-insets: 0 0 -1 0, 0, 1, 2;\r
+ -fx-background-radius: 5, 5, 4, 3;\r
+ -fx-padding: 0.266667em 0.233333em 0.25em 0.233333em;\r
+ -fx-text-fill: -fx-text-base-color;\r
+}\r
+\r
+.ListSpinner:hover {\r
+ -fx-color: -fx-hover-base;\r
+}\r
+\r
+.ListSpinner:focused { \r
+ -fx-color: -fx-focused-base;\r
+ -fx-background-color: -fx-focus-color, -fx-outer-border, -fx-inner-border, -fx-body-color;\r
+ -fx-background-insets: -1.4, 0, 1, 2;\r
+ -fx-background-radius: 6.4, 5, 4, 3; \r
+}\r
+\r
+.ListSpinner .value { \r
+ -fx-padding: 0.0em 0.2em 0.0em 0.2em;\r
+}\r
+\r
+.ListSpinner .left-arrow { \r
+ -fx-shape: "M4,-4 L0,0 L4,4 Z";\r
+ -fx-scale-shape: false;\r
+}\r
+.ListSpinner .right-arrow { \r
+ -fx-shape: "M0,-4 L4,0 L0,4 Z";\r
+ -fx-scale-shape: false;\r
+}\r
+.ListSpinner .down-arrow { \r
+ -fx-shape: "M-4,-2 L0,2 L4,-2 Z";\r
+ -fx-scale-shape: false;\r
+}\r
+.ListSpinner .up-arrow { \r
+ -fx-shape: "M4,2 L-4,2 L0,-2 Z";\r
+ -fx-scale-shape: false;\r
+}\r
+.ListSpinner .idle {\r
+ -fx-background-color: -fx-mark-color;\r
+}\r
+.ListSpinner .clicked { \r
+ -fx-background-color: -fx-focus-color;\r
+}\r
--- /dev/null
+/**
+ * Copyright (c) 2011, JFXtras
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jfxtras.labs.internal.scene.control.behavior;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javafx.scene.input.KeyCode;
+import javafx.scene.input.MouseEvent;
+import javafx.util.Callback;
+import jfxtras.labs.scene.control.ListSpinner;
+
+import com.sun.javafx.scene.control.behavior.BehaviorBase;
+import com.sun.javafx.scene.control.behavior.KeyBinding;
+
+/**
+ *
+ * @author Tom Eugelink
+ *
+ */
+public class ListSpinnerBehavior<T> extends BehaviorBase<ListSpinner<T>>
+{
+ // ==================================================================================================================
+ // CONSTRUCTOR
+
+ /**
+ *
+ * @param control
+ */
+ public ListSpinnerBehavior(ListSpinner<T> control)
+ {
+ super(control);
+ construct();
+ }
+
+ /*
+ *
+ */
+ private void construct()
+ {
+
+ }
+
+ // ==================================================================================================================
+ // EDITABLE
+
+ /**
+ * Parse the value (which usually comes from the TextField in the skin).
+ * If the value exists in the current items, select it.
+ * If not and a callback is defined, call the callback to have it handle it.
+ * Otherwise do nothing (leave it to the skin).
+ */
+ public void parse(String text)
+ {
+ // strip
+ String lText = text;
+ String lPostfix = getControl().getPostfix();
+ if (lPostfix.length() > 0 && lText.endsWith(lPostfix)) lText = lText.substring(0, lText.length() - lPostfix.length());
+ String lPrefix = getControl().getPrefix();
+ if (lPrefix.length() > 0 && lText.startsWith(lPrefix)) lText = lText.substring(lPrefix.length());
+
+ // convert from string to value
+ T lValue = getControl().getStringConverter().fromString(lText);
+
+ // if the value does exists in the domain
+ int lItemIndex = getControl().getItems().indexOf(lValue);
+ if (lItemIndex >= 0)
+ {
+ // accept value and bail out
+ getControl().setValue(lValue);
+ return;
+ }
+
+ // check to see if we have a addCallback
+ Callback<T, Integer> lAddCallback = getControl().getAddCallback();
+ if (lAddCallback != null)
+ {
+ // call the callback
+ Integer lIndex = lAddCallback.call(lValue);
+
+ // if the callback reports that it has processed the value by returning the index where it has added the item. (Or at least the index it wants to show now.)
+ if (lIndex != null)
+ {
+ // accept value and bail out
+ getControl().setIndex(lIndex);
+ return;
+ }
+ }
+ }
+
+ // ==================================================================================================================
+ // MOUSE EVENTS
+
+ /**
+ *
+ */
+ @Override public void mousePressed(MouseEvent evt)
+ {
+ // get the control
+ ListSpinner<T> lControl = getControl();
+
+ // if a control does not have the focus, request focus
+ if (!lControl.isFocused() && lControl.isFocusTraversable()) {
+ lControl.requestFocus();
+ }
+ }
+
+ // ==================================================================================================================
+ // KEY EVENTS
+
+ final static private String EVENT_PREVIOUS = "PreviousPressed";
+ final static private String EVENT_NEXT = "NextPressed";
+ protected final static List<KeyBinding> KEY_BINDINGS = new ArrayList<KeyBinding>();
+ static
+ {
+ KEY_BINDINGS.add( new KeyBinding(KeyCode.MINUS, EVENT_PREVIOUS) ); // keyboard -
+ KEY_BINDINGS.add( new KeyBinding(KeyCode.PLUS, EVENT_NEXT) ); // keyboard +
+ KEY_BINDINGS.add( new KeyBinding(KeyCode.SUBTRACT, EVENT_PREVIOUS) ); // keypad -
+ KEY_BINDINGS.add( new KeyBinding(KeyCode.ADD, EVENT_NEXT) ); // keypad +
+ KEY_BINDINGS.add(new KeyBinding(KeyCode.UP, EVENT_NEXT));
+ KEY_BINDINGS.add(new KeyBinding(KeyCode.DOWN, EVENT_PREVIOUS));
+ KEY_BINDINGS.add(new KeyBinding(KeyCode.LEFT, EVENT_PREVIOUS));
+ KEY_BINDINGS.add(new KeyBinding(KeyCode.RIGHT, EVENT_NEXT));
+ KEY_BINDINGS.addAll(TRAVERSAL_BINDINGS);
+ }
+
+ @Override protected List<KeyBinding> createKeyBindings()
+ {
+ return KEY_BINDINGS;
+ }
+
+ @Override protected void callAction(String name) {
+ if (EVENT_PREVIOUS.equals(name)) {
+ getControl().decrement();
+ }
+ else if (EVENT_NEXT.equals(name)) {
+ getControl().increment();
+ }
+ else {
+ super.callAction(name);
+ }
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2011, JFXtras
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jfxtras.labs.internal.scene.control.skin;
+
+import javafx.beans.InvalidationListener;
+import javafx.beans.Observable;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.geometry.Point2D;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.control.TextField;
+import javafx.scene.input.KeyCode;
+import javafx.scene.input.KeyEvent;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.input.ScrollEvent;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.ColumnConstraints;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.RowConstraints;
+import javafx.util.Duration;
+import jfxtras.labs.animation.Timer;
+import jfxtras.labs.internal.scene.control.behavior.ListSpinnerBehavior;
+import jfxtras.labs.scene.control.ListSpinner;
+import jfxtras.labs.scene.control.ListSpinner.ArrowDirection;
+import jfxtras.labs.scene.control.ListSpinner.ArrowPosition;
+
+import com.sun.javafx.scene.control.skin.SkinBase;
+
+/**
+ *
+ * @author Tom Eugelink
+ *
+ * Possible extension: drop down list or grid for quick selection
+ */
+public class ListSpinnerCaspianSkin<T> extends SkinBase<ListSpinner<T>, ListSpinnerBehavior<T>>
+{
+ // TODO: vertical centering
+
+ // ==================================================================================================================
+ // CONSTRUCTOR
+
+ /**
+ *
+ */
+ public ListSpinnerCaspianSkin(ListSpinner<T> control)
+ {
+ super(control, new ListSpinnerBehavior<T>(control));
+ construct();
+ }
+
+ /*
+ *
+ */
+ private void construct()
+ {
+ // setup component
+ createNodes();
+
+ // react to value changes in the model
+ getSkinnable().editableProperty().addListener(new ChangeListener<Boolean>()
+ {
+ @Override
+ public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2)
+ {
+ replaceValueNode();
+ }
+ });
+ replaceValueNode();
+
+ // react to value changes in the model
+ getSkinnable().valueProperty().addListener(new ChangeListener<T>()
+ {
+ @Override
+ public void changed(ObservableValue<? extends T> observableValue, T oldValue, T newValue)
+ {
+ refreshValue();
+ }
+ });
+ refreshValue();
+
+ // react to value changes in the model
+ getSkinnable().arrowDirectionProperty().addListener(new ChangeListener<ListSpinner.ArrowDirection>()
+ {
+ @Override
+ public void changed(ObservableValue<? extends ArrowDirection> observableValue, ArrowDirection oldValue, ArrowDirection newValue)
+ {
+ setArrowCSS();
+ layoutGridPane();
+ }
+ });
+ setArrowCSS();
+ layoutGridPane();
+
+ // react to value changes in the model
+ getSkinnable().alignmentProperty().addListener(new ChangeListener<Pos>()
+ {
+ @Override
+ public void changed(ObservableValue<? extends Pos> observableValue, Pos oldValue, Pos newValue)
+ {
+ alignValue();
+ }
+ });
+ alignValue();
+
+ }
+
+ /*
+ *
+ */
+ private void refreshValue()
+ {
+ // if editable
+ if (getSkinnable().isEditable() == true)
+ {
+ // update textfield
+ T lValue = getSkinnable().getValue();
+ textField.setText( getSkinnable().getPrefix() + getSkinnable().getStringConverter().toString(lValue) + getSkinnable().getPostfix() );
+ }
+ else
+ {
+ // get node for this value
+ Node lNode = getSkinnable().getCellFactory().call( getSkinnable() );
+ }
+ }
+
+ // ==================================================================================================================
+ // DRAW
+
+ /**
+ * Construct the nodes.
+ * Spinner uses a GridPane where the arrows and the node for the value are laid out according to the arrows direction and location.
+ * A place holder in inserted into the GridPane to hold the value node, so the spinner can alternate between editable or readonly mode, without having to recreate the GridPane.
+ */
+ private void createNodes()
+ {
+ // left arrow
+ decrementArrow = new Region();
+ decrementArrow.getStyleClass().add("idle");
+
+ // place holder for showing the value
+ valueGroup = new BorderPane();
+ valueGroup.getStyleClass().add("valuePane");
+
+ // right arrow
+ incrementArrow = new Region();
+ incrementArrow.getStyleClass().add("idle");
+
+ // construct a gridpane
+ gridPane = new GridPane();
+
+ // we're not catching the mouse events on the individual children, but let it bubble up to the parent and handle it there, this makes our life much more simple
+ // process mouse clicks
+ gridPane.setOnMouseClicked(new EventHandler<MouseEvent>()
+ {
+ @Override public void handle(MouseEvent evt)
+ {
+ // if click was the in the greater vicinity of the decrement arrow
+ if (mouseEventOverArrow(evt, decrementArrow))
+ {
+ // left
+ unclickArrows();
+ decrementArrow.getStyleClass().add("clicked");
+ getSkinnable().decrement();
+ unclickTimer.restart();
+ return;
+ }
+
+ // if click was the in the greater vicinity of the increment arrow
+ if (mouseEventOverArrow(evt, incrementArrow))
+ {
+ // right
+ unclickArrows();
+ incrementArrow.getStyleClass().add("clicked");
+ getSkinnable().increment();
+ unclickTimer.restart();
+ return;
+ }
+ }
+ });
+ // process mouse holds
+ gridPane.setOnMousePressed(new EventHandler<MouseEvent>()
+ {
+ @Override public void handle(MouseEvent evt)
+ {
+ // if click was the in the greater vicinity of the decrement arrow
+ if (mouseEventOverArrow(evt, decrementArrow))
+ {
+ // left
+ decrementArrow.getStyleClass().add("clicked");
+ repeatDecrementClickTimer.restart();
+ return;
+ }
+
+ // if click was the in the greater vicinity of the increment arrow
+ if (mouseEventOverArrow(evt, incrementArrow))
+ {
+ // right
+ incrementArrow.getStyleClass().add("clicked");
+ repeatIncrementClickTimer.restart();
+ return;
+ }
+ }
+ });
+ gridPane.setOnMouseReleased(new EventHandler<MouseEvent>()
+ {
+ @Override public void handle(MouseEvent evt)
+ {
+ unclickArrows();
+ repeatDecrementClickTimer.stop();
+ repeatIncrementClickTimer.stop();
+ }
+ });
+ gridPane.setOnMouseExited(new EventHandler<MouseEvent>()
+ {
+ @Override public void handle(MouseEvent evt)
+ {
+ unclickArrows();
+ repeatDecrementClickTimer.stop();
+ repeatIncrementClickTimer.stop();
+ }
+ });
+ // mouse wheel
+ gridPane.setOnScroll(new EventHandler<ScrollEvent>()
+ {
+ @Override
+ public void handle(ScrollEvent evt)
+ {
+ // if click was the in the greater vicinity of the decrement arrow
+ if (evt.getDeltaY() < 0 || evt.getDeltaX() < 0)
+ {
+ // left
+ unclickArrows();
+ decrementArrow.getStyleClass().add("clicked");
+ getSkinnable().decrement();
+ unclickTimer.restart();
+ return;
+ }
+
+ // if click was the in the greater vicinity of the increment arrow
+ if (evt.getDeltaY() > 0 || evt.getDeltaX() > 0)
+ {
+ // right
+ unclickArrows();
+ incrementArrow.getStyleClass().add("clicked");
+ getSkinnable().increment();
+ unclickTimer.restart();
+ return;
+ }
+ }
+ });
+
+ // add to self
+ this.getStyleClass().add(this.getClass().getSimpleName()); // always add self as style class, because CSS should relate to the skin not the control
+ getChildren().add(gridPane);
+ }
+ private Region decrementArrow = null;
+ private Region incrementArrow = null;
+ private GridPane gridPane = null;
+ private BorderPane valueGroup;
+
+ // timer to remove the click styling on the arrows after a certain delay
+ final private Timer unclickTimer = new Timer(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ unclickArrows();
+ }
+ }).withDelay(Duration.millis(100)).withRepeats(false);
+
+ // timer to handle the holding of the decrement button
+ final private Timer repeatDecrementClickTimer = new Timer(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ getSkinnable().decrement();
+ }
+ }).withDelay(Duration.millis(500)).withCycleDuration(Duration.millis(50));
+
+ // timer to handle the holding of the increment button
+ final private Timer repeatIncrementClickTimer = new Timer(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ getSkinnable().increment();
+ }
+ }).withDelay(Duration.millis(500)).withCycleDuration(Duration.millis(50));
+
+ /**
+ * Check if the mouse event is considered to have happened over the arrow
+ * @param evt
+ * @param region
+ * @return
+ */
+ private boolean mouseEventOverArrow(MouseEvent evt, Region region)
+ {
+ // if click was the in the greater vicinity of the decrement arrow
+ Point2D lClickInRelationToArrow = region.sceneToLocal(evt.getSceneX(), evt.getSceneY());
+ if ( lClickInRelationToArrow.getX() >= 0.0 && lClickInRelationToArrow.getX() <= region.getWidth()
+ && lClickInRelationToArrow.getY() >= 0.0 && lClickInRelationToArrow.getY() <= region.getHeight()
+ )
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Remove clicked CSS styling from the arrows
+ */
+ private void unclickArrows()
+ {
+ decrementArrow.getStyleClass().remove("clicked");
+ incrementArrow.getStyleClass().remove("clicked");
+ }
+
+ /**
+ * Put the correct node for the value's place holder:
+ * - either the TextField when in editable mode,
+ * - or a node generated by the cell factory when in readonly mode.
+ */
+ private void replaceValueNode()
+ {
+ // clear
+ valueGroup.getChildren().clear();
+
+ // if not editable
+ if (getSkinnable().isEditable() == false)
+ {
+ // use the cell factory
+ Node lNode = getSkinnable().getCellFactory().call(getSkinnable());
+ valueGroup.setCenter( lNode );
+ if (lNode.getStyleClass().contains("value") == false) lNode.getStyleClass().add("value");
+ if (lNode.getStyleClass().contains("readonly") == false) lNode.getStyleClass().add("readonly");
+ }
+ else
+ {
+ // use the textfield
+ if (textField == null)
+ {
+ textField = new TextField();
+ textField.getStyleClass().add("value");
+ textField.getStyleClass().add("editable");
+
+ // process text entry
+ textField.focusedProperty().addListener(new InvalidationListener()
+ {
+ @Override
+ public void invalidated(Observable arg0)
+ {
+ if (textField.isFocused() == false)
+ {
+ parse(textField);
+ }
+ }
+ });
+ textField.setOnAction(new EventHandler<ActionEvent>()
+ {
+ @Override
+ public void handle(ActionEvent evt)
+ {
+ parse(textField);
+ }
+ });
+ textField.setOnKeyPressed(new EventHandler<KeyEvent>()
+ {
+ @Override public void handle(KeyEvent t)
+ {
+ if (t.getCode() == KeyCode.ESCAPE)
+ {
+ // refresh
+ refreshValue();
+ }
+ }
+ });
+
+ // alignment
+ textField.alignmentProperty().bind(getSkinnable().alignmentProperty());
+ }
+ valueGroup.setCenter(textField);
+ }
+
+ // align
+ alignValue();
+ }
+ private TextField textField = null;
+
+ /**
+ * align the value inside the plave holder
+ */
+ private void alignValue()
+ {
+ // valueGroup always only holds one child (the value)
+ BorderPane.setAlignment(valueGroup.getChildren().get(0), getSkinnable().alignmentProperty().getValue());
+ }
+
+ // ==================================================================================================================
+ // EDITABLE
+
+ /**
+ * Parse the contents of the textfield
+ * @param textField
+ */
+ protected void parse(TextField textField)
+ {
+ // get the text to parse
+ String lText = textField.getText();
+
+ // process it
+ getBehavior().parse(lText);
+
+ // refresh
+ refreshValue();
+ return;
+ }
+
+ /**
+ * Lays out the spinner, depending on the location and direction of the arrows.
+ */
+ private void layoutGridPane()
+ {
+ // get the things we decide on
+ ArrowDirection lArrowDirection = getSkinnable().getArrowDirection();
+ ArrowPosition lArrowPosition = getSkinnable().getArrowPosition();
+
+ // get helper values
+ ColumnConstraints lColumnValue = new ColumnConstraints(valueGroup.getMinWidth(), valueGroup.getPrefWidth(), Double.MAX_VALUE);
+ lColumnValue.setHgrow(Priority.ALWAYS);
+ ColumnConstraints lColumnArrow = new ColumnConstraints(10);
+
+ // get helper values
+ RowConstraints lRowValue = new RowConstraints(valueGroup.getMinHeight(), valueGroup.getPrefHeight(), Double.MAX_VALUE);
+ lRowValue.setVgrow(Priority.ALWAYS);
+ RowConstraints lRowArrow = new RowConstraints(10);
+
+ // clear the grid
+ gridPane.getChildren().clear();
+ gridPane.getColumnConstraints().clear();
+ gridPane.getRowConstraints().clear();
+ //gridPane.setGridLinesVisible(true);
+
+ if (lArrowDirection == ArrowDirection.HORIZONTAL)
+ {
+ if (lArrowPosition == ArrowPosition.LEADING)
+ {
+ // construct a gridpane: one row, three columns: arrow, arrow, value
+ gridPane.setHgap(3);
+ gridPane.setVgap(0);
+ gridPane.add(decrementArrow, 0, 0);
+ gridPane.add(incrementArrow, 1, 0);
+ gridPane.add(valueGroup, 2, 0);
+ gridPane.getColumnConstraints().addAll(lColumnArrow, lColumnArrow, lColumnValue);
+ }
+ if (lArrowPosition == ArrowPosition.TRAILING)
+ {
+ // construct a gridpane: one row, three columns: value, arrow, arrow
+ gridPane.setHgap(3);
+ gridPane.setVgap(0);
+ gridPane.add(valueGroup, 0, 0);
+ gridPane.add(decrementArrow, 1, 0);
+ gridPane.add(incrementArrow, 2, 0);
+ gridPane.getColumnConstraints().addAll(lColumnValue, lColumnArrow, lColumnArrow);
+ }
+ if (lArrowPosition == ArrowPosition.SPLIT)
+ {
+ // construct a gridpane: one row, three columns: arrow, value, arrow
+ gridPane.setHgap(3);
+ gridPane.setVgap(0);
+ gridPane.add(decrementArrow, 0, 0);
+ gridPane.add(valueGroup, 1, 0);
+ gridPane.add(incrementArrow, 2, 0);
+ gridPane.getColumnConstraints().addAll(lColumnArrow, lColumnValue, lColumnArrow);
+ }
+ }
+ if (lArrowDirection == ArrowDirection.VERTICAL)
+ {
+ if (lArrowPosition == ArrowPosition.LEADING)
+ {
+ // construct a gridpane: two rows, two columns: arrows on top, value
+ gridPane.setHgap(3);
+ gridPane.setVgap(0);
+ gridPane.add(incrementArrow, 0, 0);
+ gridPane.add(decrementArrow, 0, 1);
+ gridPane.add(valueGroup, 1, 0, 1, 2);
+ gridPane.getColumnConstraints().addAll(lColumnArrow, lColumnValue);
+ gridPane.getRowConstraints().addAll(lRowArrow, lRowArrow);
+ }
+ if (lArrowPosition == ArrowPosition.TRAILING)
+ {
+ // construct a gridpane: two rows, two columns: value, arrows on top
+ gridPane.setHgap(3);
+ gridPane.setVgap(0);
+ gridPane.add(valueGroup, 0, 0, 1, 2);
+ gridPane.add(incrementArrow, 1, 0);
+ gridPane.add(decrementArrow, 1, 1);
+ gridPane.getColumnConstraints().addAll(lColumnValue, lColumnArrow);
+ gridPane.getRowConstraints().addAll(lRowArrow, lRowArrow);
+ }
+ if (lArrowPosition == ArrowPosition.SPLIT)
+ {
+ // construct a gridpane: three rows, one columns: arrow, value, arrow
+ gridPane.setHgap(3);
+ gridPane.setVgap(0);
+ gridPane.add(incrementArrow, 0, 0);
+ gridPane.add(valueGroup, 0, 1);
+ gridPane.add(decrementArrow, 0, 2);
+ gridPane.getColumnConstraints().addAll(lColumnValue);
+ gridPane.getRowConstraints().addAll(lRowArrow, lRowValue, lRowArrow);
+ }
+ }
+ }
+
+ /**
+ * Set the CSS according to the direction of the arrows, so the correct arrows are shown
+ */
+ private void setArrowCSS()
+ {
+ if (getSkinnable().getArrowDirection().equals(ListSpinner.ArrowDirection.HORIZONTAL))
+ {
+ decrementArrow.getStyleClass().add("left-arrow");
+ incrementArrow.getStyleClass().add("right-arrow");
+ }
+ else
+ {
+ decrementArrow.getStyleClass().add("down-arrow");
+ incrementArrow.getStyleClass().add("up-arrow");
+ }
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2011, JFXtras
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jfxtras.labs.scene.control;
+
+import java.util.Arrays;
+
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
+import javafx.event.Event;
+import javafx.event.EventHandler;
+import javafx.event.EventTarget;
+import javafx.event.EventType;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.control.Control;
+import javafx.scene.control.Label;
+import javafx.util.Callback;
+import javafx.util.StringConverter;
+
+/**
+ * This is a spinner, showing one value at a time from a list.
+ * This value is set and retrieved from the value property.
+ * Basically a spinner shows a list of values and can do "next" or "previous" on this.
+ *
+ * A spinner can be editable, the user can then type a value instead of selecting it.
+ * If the value exists in the list, the spinner will simply jump to it.
+ * If the value does not exist, if defined the AddCallback is called.
+ * - If the AddCallback returns null, spinner will only refresh the current index.
+ * - If the AddCallback returns an Integer, spinner will jump to that index (usually the index where the new value was added).
+ *
+ * http://openjdk.java.net/projects/openjfx/ux/spinner/index.html
+ *
+ * You can style the text in the control using CSS like so:
+ * .ListSpinner .value {
+ * -fx-font-weight: bold;
+ * }
+ *
+ * The "value" class applies to the text in both readonly and editable spinners. Use "readonly" or "editable" to style either mode specifically.
+ *
+ * @author Tom Eugelink
+ */
+public class ListSpinner<T> extends Control
+{
+ // TODO: implement SelectionModel?
+ // ==================================================================================================================
+ // CONSTRUCTOR
+
+ /**
+ */
+ public ListSpinner()
+ {
+ construct();
+ }
+
+ // ------------
+ // model
+
+ /**
+ * @param items The item list used to populate the spinner.
+ */
+ public ListSpinner(ObservableList<T> items)
+ {
+ construct();
+ setItems(items);
+ first();
+ }
+
+ /**
+ * @param items The item list used to populate the spinner.
+ * @param startValue The initial value of the spinner (one of the items).
+ */
+ public ListSpinner(ObservableList<T> items, T startValue)
+ {
+ construct();
+ setItems(items);
+ setValue(startValue);
+ }
+
+ // ------------
+ // convenience
+
+ /**
+ * @param list
+ */
+ public ListSpinner(java.util.List<T> list)
+ {
+ this( FXCollections.observableList(list) );
+ }
+
+ /**
+ * @param list
+ */
+ public ListSpinner(T... list)
+ {
+ this( Arrays.asList(list) );
+ }
+
+ /**
+ * @param from
+ * @param to
+ */
+ public ListSpinner(int from, int to)
+ {
+ this( (java.util.List<T>) new ListSpinnerIntegerList(from, to) );
+ }
+
+ /**
+ * @param from
+ * @param to
+ * @param step
+ */
+ public ListSpinner(int from, int to, int step)
+ {
+ this( (java.util.List<T>) new ListSpinnerIntegerList(from, to, step) );
+ }
+
+ // ------------
+
+ /*
+ *
+ */
+ private void construct()
+ {
+ // setup the CSS
+ // the -fx-skin attribute in the CSS sets which Skin class is used
+ this.getStyleClass().add(this.getClass().getSimpleName());
+
+ // react to changes of the value
+ this.valueObjectProperty.addListener(new ChangeListener<T>()
+ {
+ @Override
+ public void changed(ObservableValue<? extends T> property, T oldValue, T newValue)
+ {
+ // get the value of the new index
+ int lIdx = getItems().indexOf(newValue);
+
+ // set the value
+ if (ListSpinner.equals(indexObjectProperty.getValue(), lIdx) == false)
+ {
+ indexObjectProperty.setValue(lIdx);
+ }
+ }
+ });
+
+ // react to changes of the index
+ this.indexObjectProperty.addListener(new ChangeListener<Integer>()
+ {
+ @Override
+ public void changed(ObservableValue<? extends Integer> property, Integer oldIndex, Integer newIndex)
+ {
+ // get the value of the new index
+ T lValue = newIndex < 0 ? null : getItems().get(newIndex);
+
+ // set the value
+ if (ListSpinner.equals(valueObjectProperty.getValue(), lValue) == false)
+ {
+ valueObjectProperty.setValue(lValue);
+ }
+ }
+ });
+
+ // react to changes of the items
+ this.itemsObjectProperty.addListener(new ChangeListener<ObservableList<T>>()
+ {
+ @Override
+ public void changed(ObservableValue<? extends ObservableList<T>> property, ObservableList<T> oldList, ObservableList<T> newList)
+ {
+ if (oldList != null) oldList.removeListener(listChangeListener);
+ if (newList != null) newList.addListener(listChangeListener);
+ }
+ });
+ }
+
+ /*
+ * react to observable list changes
+ * TODO: what is sticky, index or value? Now: index
+ */
+ private ListChangeListener<T> listChangeListener = new ListChangeListener<T>()
+ {
+ @Override
+ public void onChanged(javafx.collections.ListChangeListener.Change<? extends T> change)
+ {
+ // get current index
+ int lIndex = getIndex();
+
+ // is it still valid?
+ if (lIndex >= getItems().size())
+ {
+ lIndex = getItems().size() - 1;
+ setIndex(lIndex);
+ return;
+ }
+
+ // (re)set the value of the index
+ valueObjectProperty.setValue( getItems().get(lIndex) );
+ }
+ };
+
+ /**
+ * Return the path to the CSS file so things are setup right
+ */
+ @Override protected String getUserAgentStylesheet()
+ {
+ return this.getClass().getResource("/jfxtras/labs/internal/scene/control/" + this.getClass().getSimpleName() + ".css").toString();
+ }
+
+ // ==================================================================================================================
+ // PROPERTIES
+
+ /** Value: */
+ public ObjectProperty<T> valueProperty() { return this.valueObjectProperty; }
+ final private ObjectProperty<T> valueObjectProperty = new SimpleObjectProperty<T>(this, "value", null)
+ {
+ public void set(T value)
+ {
+ if (getItems().indexOf(value) < 0) throw new IllegalArgumentException("Value does not exist in the list: " + value);
+ super.set(value);
+ }
+ };
+ // java bean API
+ public T getValue() { return this.valueObjectProperty.getValue(); }
+ public void setValue(T value) { this.valueObjectProperty.setValue(value); }
+ public ListSpinner<T> withValue(T value) { setValue(value); return this; }
+
+ /** Index: */
+ public ObjectProperty<Integer> indexProperty() { return this.indexObjectProperty; }
+ final private ObjectProperty<Integer> indexObjectProperty = new SimpleObjectProperty<Integer>(this, "index", null)
+ {
+ public void set(Integer value)
+ {
+ if (value == null) throw new NullPointerException("Null not allowed as the value for index");
+ if (value >= getItems().size()) throw new IllegalArgumentException("Index out of bounds: " + value + ", valid values are 0-" + (getItems().size() - 1));
+ super.set(value);
+ }
+ };
+ public Integer getIndex() { return this.indexObjectProperty.getValue(); }
+ public void setIndex(Integer value) { this.indexObjectProperty.setValue(value); }
+ public ListSpinner<T> withIndex(Integer value) { setIndex(value); return this; }
+
+ /** Cyclic: */
+ public ObjectProperty<Boolean> cyclicProperty() { return this.cyclicObjectProperty; }
+ final private ObjectProperty<Boolean> cyclicObjectProperty = new SimpleObjectProperty<Boolean>(this, "cyclic", false)
+ {
+ public void set(Boolean value)
+ {
+ if (value == null) throw new NullPointerException("Null not allowed as the value for cyclic");
+ super.set(value);
+ }
+ };
+ public Boolean isCyclic() { return this.cyclicObjectProperty.getValue(); }
+ public void setCyclic(Boolean value) { this.cyclicObjectProperty.setValue(value); }
+ public ListSpinner<T> withCyclic(Boolean value) { setCyclic(value); return this; }
+
+ /** Editable: */
+ public ObjectProperty<Boolean> editableProperty() { return this.editableObjectProperty; }
+ final private ObjectProperty<Boolean> editableObjectProperty = new SimpleObjectProperty<Boolean>(this, "editable", false)
+ {
+ public void set(Boolean value)
+ {
+ if (value == null) throw new NullPointerException("Null not allowed as the value for editable");
+ super.set(value);
+ }
+ };
+ public Boolean isEditable() { return this.editableObjectProperty.getValue(); }
+ public void setEditable(Boolean value) { this.editableObjectProperty.setValue(value); }
+ public ListSpinner<T> withEditable(Boolean value) { setEditable(value); return this; }
+
+ /** Postfix: */
+ public ObjectProperty<String> postfixProperty() { return this.postfixObjectProperty; }
+ final private ObjectProperty<String> postfixObjectProperty = new SimpleObjectProperty<String>(this, "postfix", "");
+ public String getPostfix() { return this.postfixObjectProperty.getValue(); }
+ public void setPostfix(String value) { this.postfixObjectProperty.setValue(value); }
+ public ListSpinner<T> withPostfix(String value) { setPostfix(value); return this; }
+
+ /** Prefix: */
+ public ObjectProperty<String> prefixProperty() { return this.prefixObjectProperty; }
+ final private ObjectProperty<String> prefixObjectProperty = new SimpleObjectProperty<String>(this, "prefix", "");
+ public String getPrefix() { return this.prefixObjectProperty.getValue(); }
+ public void setPrefix(String value) { this.prefixObjectProperty.setValue(value); }
+ public ListSpinner<T> withPrefix(String value) { setPrefix(value); return this; }
+
+ /** Items: */
+ public ObjectProperty<ObservableList<T>> itemsProperty() { return this.itemsObjectProperty; }
+ final private ObjectProperty<ObservableList<T>> itemsObjectProperty = new SimpleObjectProperty<ObservableList<T>>(this, "items", null)
+ {
+ public void set(ObservableList<T> value)
+ {
+ if (value == null) throw new NullPointerException("Null not allowed as the value for items");
+ super.set(value);
+ }
+ };
+ public ObservableList<T> getItems() { return this.itemsObjectProperty.getValue(); }
+ public void setItems(ObservableList<T> value) { this.itemsObjectProperty.setValue(value); }
+ public ListSpinner<T> withItems(ObservableList<T> value) { setItems(value); return this; }
+
+ /** CellFactory: */
+ public ObjectProperty<Callback<ListSpinner<T>, Node>> cellFactoryProperty() { return this.cellFactoryObjectProperty; }
+ final private ObjectProperty<Callback<ListSpinner<T>, Node>> cellFactoryObjectProperty = new SimpleObjectProperty<Callback<ListSpinner<T>, Node>>(this, "cellFactory", new DefaultCellFactory());
+ public Callback<ListSpinner<T>, Node> getCellFactory() { return this.cellFactoryObjectProperty.getValue(); }
+ public void setCellFactory(Callback<ListSpinner<T>, Node> value) { this.cellFactoryObjectProperty.setValue(value); }
+ public ListSpinner<T> withCellFactory(Callback<ListSpinner<T>, Node> value) { setCellFactory(value); return this; }
+
+ /** StringConverter<T>: */
+ public ObjectProperty<StringConverter<T>> stringConverterProperty() { return this.stringConverterObjectProperty; }
+ final private ObjectProperty<StringConverter<T>> stringConverterObjectProperty = new SimpleObjectProperty<StringConverter<T>>(this, "stringConverter", new DefaultStringConverter());
+ public StringConverter<T> getStringConverter() { return this.stringConverterObjectProperty.getValue(); }
+ public void setStringConverter(StringConverter<T> value) { this.stringConverterObjectProperty.setValue(value); }
+ public ListSpinner<T> withStringConverter(StringConverter<T> value) { setStringConverter(value); return this; }
+
+ /** ArrowDirection: */
+ public ObjectProperty<ArrowDirection> arrowDirectionProperty() { return this.arrowDirectionObjectProperty; }
+ final private ObjectProperty<ArrowDirection> arrowDirectionObjectProperty = new SimpleObjectProperty<ArrowDirection>(this, "arrowDirection", ArrowDirection.HORIZONTAL)
+ {
+ public void set(ArrowDirection value)
+ {
+ if (value == null) throw new NullPointerException("Null not allowed as the value for arrowDirection");
+ super.set(value);
+ }
+ };
+ public ArrowDirection getArrowDirection() { return this.arrowDirectionObjectProperty.getValue(); }
+ public void setArrowDirection(ArrowDirection value) { this.arrowDirectionObjectProperty.setValue(value); }
+ public ListSpinner<T> withArrowDirection(ArrowDirection value) { setArrowDirection(value); return this; }
+ public enum ArrowDirection {VERTICAL, HORIZONTAL}
+
+ /** ArrowPosition: */
+ public ObjectProperty<ArrowPosition> arrowPositionProperty() { return this.arrowPositionObjectProperty; }
+ final private ObjectProperty<ArrowPosition> arrowPositionObjectProperty = new SimpleObjectProperty<ArrowPosition>(this, "arrowPosition", ArrowPosition.TRAILING)
+ {
+ public void set(ArrowPosition value)
+ {
+ if (value == null) throw new NullPointerException("Null not allowed as the value for arrowPosition");
+ super.set(value);
+ }
+ };
+ public ArrowPosition getArrowPosition() { return this.arrowPositionObjectProperty.getValue(); }
+ public void setArrowPosition(ArrowPosition value) { this.arrowPositionObjectProperty.setValue(value); }
+ public ListSpinner<T> withArrowPosition(ArrowPosition value) { setArrowPosition(value); return this; }
+ public enum ArrowPosition {LEADING, TRAILING, SPLIT}
+
+ /** Alignment: only applicable in non edit mode */
+ public ObjectProperty<Pos> alignmentProperty() { return this.alignmentObjectProperty; }
+ final private ObjectProperty<Pos> alignmentObjectProperty = new SimpleObjectProperty<Pos>(this, "alignment", Pos.CENTER_LEFT)
+ {
+ public void set(Pos value)
+ {
+ if (value == null) throw new NullPointerException("Null not allowed as the value for alignment");
+ super.set(value);
+ }
+ };
+ public Pos isAlignment() { return this.alignmentObjectProperty.getValue(); }
+ public void setAlignment(Pos value) { this.alignmentObjectProperty.setValue(value); }
+ public ListSpinner<T> withAlignment(Pos value) { setAlignment(value); return this; }
+
+ /** AddCallback: */
+ public ObjectProperty<Callback<T, Integer>> addCallbackProperty() { return this.addCallbackObjectProperty; }
+ final private ObjectProperty<Callback<T, Integer>> addCallbackObjectProperty = new SimpleObjectProperty<Callback<T, Integer>>(this, "addCallback", null);
+ public Callback<T, Integer> getAddCallback() { return this.addCallbackObjectProperty.getValue(); }
+ public void setAddCallback(Callback<T, Integer> value) { this.addCallbackObjectProperty.setValue(value); }
+ public ListSpinner<T> withAddCallback(Callback<T, Integer> value) { setAddCallback(value); return this; }
+
+ // ==================================================================================================================
+ // StringConverter
+
+ /**
+ * A string converter that does a simple toString, but cannot convert to an object
+ * @see org.jfxextras.util.StringConverterFactory
+ */
+ class DefaultStringConverter extends StringConverter<T>
+ {
+ @Override
+ public T fromString(String string)
+ {
+ throw new IllegalStateException("No StringConverter is set. An editable Spinner must have a StringConverter to be able to render and parse the value.");
+ }
+
+ @Override
+ public String toString(T value)
+ {
+ return value == null ? "" : value.toString();
+ }
+ }
+
+ // ==================================================================================================================
+ // CellFactory
+
+ /**
+ * Default cell factory
+ */
+ class DefaultCellFactory implements Callback<ListSpinner<T>, Node>
+ {
+ private Label label = null;
+
+ @Override
+ public Node call(ListSpinner<T> spinner)
+ {
+ // get value
+ T lValue = spinner.getValue();
+
+ // label not yet created
+ if (this.label == null)
+ {
+ this.label = new Label();
+ }
+ this.label.setText( lValue == null ? "" : spinner.getPrefix() + getStringConverter().toString(lValue) + spinner.getPostfix() );
+ return this.label;
+ }
+ };
+
+ // ==================================================================================================================
+ // EVENTS
+
+ /** OnCycle: */
+ public ObjectProperty<EventHandler<CycleEvent>> onCycleProperty() { return iOnCycleObjectProperty; }
+ final private ObjectProperty<EventHandler<CycleEvent>> iOnCycleObjectProperty = new SimpleObjectProperty<EventHandler<CycleEvent>>(null);
+ // java bean API
+ public EventHandler<CycleEvent> getOnCycle() { return iOnCycleObjectProperty.getValue(); }
+ public void setOnCycle(EventHandler<CycleEvent> value) { iOnCycleObjectProperty.setValue(value); }
+ public ListSpinner<T> withOnCycle(EventHandler<CycleEvent> value) { setOnCycle(value); return this; }
+ final static public String ONCYCLE_PROPERTY_ID = "onCycle";
+
+ /**
+ * CycleEvent
+ */
+ static public class CycleEvent extends Event
+ {
+ /**
+ *
+ */
+ public CycleEvent()
+ {
+ super(new EventType<CycleEvent>());
+ }
+
+ /**
+ *
+ * @param source
+ * @param target
+ */
+ public CycleEvent(Object source, EventTarget target)
+ {
+ super(source, target, new EventType<CycleEvent>());
+ }
+
+ public Object getOldIdx() { return this.oldIdx; }
+ private Object oldIdx;
+
+ public Object getNewIdx() { return this.newIdx; }
+ private Object newIdx;
+
+
+ public boolean cycledDown() { return cycleDirection == CycleDirection.TOP_TO_BOTTOM; }
+ public boolean cycledUp() { return cycleDirection == CycleDirection.BOTTOM_TO_TOP; }
+ CycleDirection cycleDirection;
+ }
+
+ /**
+ * we're cycling, fire the event
+ */
+ public void fireCycleEvent(CycleDirection cycleDirection)
+ {
+ EventHandler<CycleEvent> lCycleEventHandler = getOnCycle();
+ if (lCycleEventHandler != null)
+ {
+ CycleEvent lCycleEvent = new CycleEvent();
+ lCycleEvent.cycleDirection = cycleDirection;
+ lCycleEventHandler.handle(lCycleEvent);
+ }
+ }
+ static public enum CycleDirection { TOP_TO_BOTTOM, BOTTOM_TO_TOP }
+
+
+ // ==================================================================================================================
+ // BEHAVIOR
+
+ /**
+ *
+ */
+ public void first()
+ {
+ // nothing to do
+ if (getItems() == null || getItems().size() == 0) return;
+
+ // set the new index (this will update the value)
+ indexObjectProperty.setValue(0);
+ }
+
+ /**
+ *
+ */
+ public void decrement()
+ {
+ // nothing to do
+ if (getItems() == null || getItems().size() == 0) return;
+
+ // get the current index
+ int lOldIdx = this.indexObjectProperty.getValue();
+
+ // get the previous index (usually current - 1)
+ int lIdx = lOldIdx - 1;
+
+ // if end
+ if (lIdx < 0)
+ {
+ // if we're not cyclic
+ if (isCyclic() != null && isCyclic().booleanValue() == false)
+ {
+ // do nothing
+ return;
+ }
+
+ // cycle to the other end: get the last value
+ lIdx = getItems().size() - 1;
+
+ // notify listener that we've cycled
+ fireCycleEvent(CycleDirection.BOTTOM_TO_TOP);
+ }
+
+ // set the new index (this will update the value)
+ indexObjectProperty.setValue(lIdx);
+ }
+
+ /**
+ *
+ */
+ public void increment()
+ {
+ // nothing to do
+ if (getItems() == null || getItems().size() == 0) return;
+
+ // get the current index
+ int lOldIdx = this.indexObjectProperty.getValue();
+
+ // get the next index (usually current + 1)
+ int lIdx = lOldIdx + 1;
+
+ // if null is return, there is no next index (usually current + 1)
+ if (lIdx >= getItems().size())
+ {
+ // if we're not cyclic
+ if (isCyclic() != null && isCyclic().booleanValue() == false)
+ {
+ // do nothing
+ return;
+ }
+
+ // cycle to the other end: get the first value
+ lIdx = 0;
+
+ // notify listener that we've cycled
+ fireCycleEvent(CycleDirection.TOP_TO_BOTTOM);
+ }
+
+ // set the new index (this will update the value)
+ indexObjectProperty.setValue(lIdx);
+ }
+
+ /**
+ * Get the last index; if the data provide is endless, this method mail fail!
+ */
+ public void last()
+ {
+ // nothing to do
+ if (getItems() == null || getItems().size() == 0) return;
+
+ // set the new index (this will update the value)
+ indexObjectProperty.setValue(getItems().size() - 1);
+ }
+
+ /**
+ * Does a o1.equals(o2) but also checks if o1 or o2 are null.
+ * @param o1
+ * @param o2
+ * @return True if the two values are equal, false otherwise.
+ */
+ static public boolean equals(Object o1, Object o2)
+ {
+ if ( o1 == null && o2 == null ) return true;
+ if ( o1 != null && o2 == null ) return false;
+ if ( o1 == null && o2 != null ) return false;
+ // TODO: compare arrays if (o1.getClass().isArray() && o2.getClass().isArray()) return Arrays.equals( (Object[])o1, (Object[])o2 );
+ return o1.equals(o2);
+ }
+
+}
--- /dev/null
+package jfxtras.labs.scene.control;
+
+/**
+ * Items for Spinner providing an integer range without actually creating a list with all values.
+ */
+public class ListSpinnerIntegerList extends java.util.AbstractList<Integer>
+{
+ /**
+ *
+ */
+ public ListSpinnerIntegerList()
+ {
+ this( (Integer.MIN_VALUE / 2) + 1, Integer.MAX_VALUE / 2, 1);
+ }
+
+ /**
+ *
+ * @param from
+ * @param to
+ */
+ public ListSpinnerIntegerList(int from, int to)
+ {
+ this(from, to, from > to ? -1 : 1);
+ }
+
+ /**
+ *
+ * @param from
+ * @param to
+ * @param step
+ */
+ public ListSpinnerIntegerList(int from, int to, int step)
+ {
+ this.from = from;
+ this.size = ((to - from) / step) + 1;
+ if (size < 0) throw new IllegalArgumentException("This results in a negative size: " + from + ", " + to + "," + step);
+ this.step = step;
+ }
+ private int from;
+ private int size;
+ private int step;
+
+
+ // ===============================================================================
+ // List interface
+
+ @Override
+ public Integer get(int index)
+ {
+ if (index < 0) throw new IllegalArgumentException("Index cannot be < 0: " + index);
+ int lValue = this.from + (index * this.step);
+ return lValue;
+ }
+
+ @Override
+ public int indexOf(Object o)
+ {
+ // calculate the index
+ int lValue = ((Integer)o).intValue();
+ int lIndex = (lValue - this.from) / this.step;
+ if (lIndex < 0 || lIndex > size) return -1;
+
+ // check if that what is at the index matches with out value
+ Integer lValueAtIndex = get(lIndex);
+ if (o.equals(lValueAtIndex) == false) return -1;
+
+ // found it
+ return lIndex;
+ }
+
+ @Override
+ public int size()
+ {
+ return this.size;
+ }
+}
\ No newline at end of file