Merge branch 'hud'

Conflicts:
	src/net/mosstest/servercore/RenderProcessor.java
	src/net/mosstest/servercore/serialization/IByteArrayWritable.java
	src/net/mosstest/servercore/serialization/LevelDBBackedMap.java
master
rarkenin 2014-07-15 20:20:21 -04:00
commit b01feae74d
56 changed files with 2059 additions and 2450 deletions

View File

@ -1,6 +1,3 @@
<<<<<<< HEAD
language: java
=======
language: java
jdk:
- oraclejdk8
@ -13,4 +10,3 @@ notifications:
- "%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}"
- "Change view : %{compare_url}"
- "Build details : %{build_url}"
>>>>>>> origin

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<etag-cache/>

View File

@ -7,4 +7,26 @@ Pull requesters:
Don't touch the thread pool or the scripting interface.
Electrocution, drowning, or security bots attacking you may occur.
pom.xml refers to non-maven jars in a custom jMonkey reporitory. Please hold as our server will have that repository available for download soon.
pom.xml refers to non-maven jars in a custom jMonkey repository. `pom.xml` refers to that repository, although it may go down when the forum or wiki goes down for updates or maintenance.
## Licensing and legalities
The entire project is licensed under the GNU GPLv3 or higher.
The burden of ensuring license compatibility for scripts is delegated to the script author. Server operators and players are not responsible
for non-compliant scripts. As obfuscated, "JSfuck"ed, minified, or otherwise non-original script files are not "the preferred way of making modifications"
they may not be used as scripts without permission from the authors. As a courtesy, please comment scripts, although comments are not required.
## Privacy laws
The authors of a script, or the Mosstest developers will not be responsible for violations of privacy laws in any jurisdictions. The burden of ensuring privacy laws are followed is delegated to server owners (as a courtesy, script authors should explicitly state what data is collected by their scripts)
The Mosstest engine itself receives, and may *collect in any format, including the database or logfiles*, player usernames, IP addresses, and passwords.
In addition, operating system and network details may be collected as an artifact of network communication, for example where OS-specific or network-equipment-specific "quirks" of how network connections are created and negotiated, or details such as text encodings or line ending characters are recorded in these logs. By running this software, the user acknowledges the recording and potential use of these details, by any game server.
## Security
While Mosstest strives to be secure, the script sandbox on a client will execute code given by a server. In case of a security breach, a rogue server can compromise a client. Please play on untrusted servers at your own risk.
If you believe a security bug exists, please report it at [Launchpad](https://bugs.launchpad.net/mosstest/+filebug). Before submitting, please mark it as private security. Developers will make it public as soon as reasonably possible.

2
build.sh Executable file
View File

@ -0,0 +1,2 @@
/usr/lib/jvm/java-8-oracle/bin/java -classpath /usr/share/maven/boot/plexus-classworlds-2.x.jar -Dclassworlds.conf=/usr/share/maven/bin/m2.conf -Dmaven.home=/usr/share/maven org.codehaus.plexus.classworlds.launcher.Launcher clean compile

BIN
builtins/crosshair.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

View File

@ -1,144 +1,178 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mosstest</groupId>
<artifactId>mosstest</artifactId>
<name>Mosstest</name>
<version>0.1.0-SNAPSHOT</version>
<description>Open-source InfiniMiner remake</description>
<url>https://github.com/mosstest/mosstest</url>
<issueManagement>
<system>Launchpad</system>
<url>https://bugs.launchpad.net/mosstest</url>
</issueManagement>
<ciManagement>
<system>Travis-CI</system>
</ciManagement>
<build>
<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>tests</testSourceDirectory>
<resources>
<resource>
<directory>src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>2.1.7</version>
<executions>
<execution>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<prefix>git</prefix>
<dateFormat>yyyy.MM.dd '@' HH:mm:ss z</dateFormat>
<verbose>true</verbose>
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
<skipPoms>true</skipPoms>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>src/git.properties</generateGitPropertiesFilename>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
<gitDescribe>
<skip>false</skip>
<always>false</always>
<abbrev>7</abbrev>
<dirty>-dirty</dirty>
<forceLongFormat>false</forceLongFormat>
</gitDescribe>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<excludes>
<exclude>bouncycastle:bcprov-jdk15</exclude>
</excludes>
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer>
<mainClass>net.mosstest.servercore.MossWorld</mainClass>
</transformer>
<transformer>
<resource>properties.properties</resource>
</transformer>
<transformer>
<resource>applicationContext.xml</resource>
</transformer>
<transformer>
<resource>META-INF/cxf/cxf.extension</resource>
</transformer>
<transformer>
<resource>META-INF/cxf/bus-extensions.xml</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>Central Repository</name>
<url>http://repo.maven.apache.org/maven2</url>
</repository>
<repository>
<id>moss-forums</id>
<url>http://forum-mosstest.rhcloud.com/repository/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.lwjgl.lwjgl</groupId>
<artifactId>parent</artifactId>
<version>2.9.0</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mosstest</groupId>
<artifactId>mosstest</artifactId>
<name>Mosstest</name>
<version>0.1.0-SNAPSHOT</version>
<<<<<<< HEAD
<description>Open-source InfiniMiner remake</description>
=======
<description>Open-source voxel engine with some extra features</description>
>>>>>>> netclient
<url>https://github.com/mosstest/mosstest</url>
<issueManagement>
<system>Launchpad</system>
<url>https://bugs.launchpad.net/mosstest</url>
</issueManagement>
<ciManagement>
<system>Travis-CI</system>
</ciManagement>
<build>
<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>tests</testSourceDirectory>
<resources>
<resource>
<directory>src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<<<<<<< HEAD
=======
<groupId>org.codehaus.mojo</groupId>
<artifactId>deb-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<phase>package</phase>
</execution>
</executions>
<configuration>
<description>An open-source voxel game created in Java</description>
<maintainer>hexafraction &lt;hexafraction@gmail.com&gt;</maintainer>
<section>games</section>
<priority>optional</priority>
<architecture>all</architecture>
</configuration>
</plugin>
<plugin>
>>>>>>> netclient
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>2.1.7</version>
<executions>
<execution>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<prefix>git</prefix>
<dateFormat>yyyy.MM.dd '@' HH:mm:ss z</dateFormat>
<verbose>true</verbose>
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
<skipPoms>true</skipPoms>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>src/git.properties</generateGitPropertiesFilename>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
<gitDescribe>
<skip>false</skip>
<always>false</always>
<abbrev>7</abbrev>
<dirty>-dirty</dirty>
<forceLongFormat>false</forceLongFormat>
</gitDescribe>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<excludes>
<exclude>bouncycastle:bcprov-jdk15</exclude>
</excludes>
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer>
<mainClass>net.mosstest.servercore.MossWorld</mainClass>
</transformer>
<transformer>
<resource>properties.properties</resource>
</transformer>
<transformer>
<resource>applicationContext.xml</resource>
</transformer>
<transformer>
<resource>META-INF/cxf/cxf.extension</resource>
</transformer>
<transformer>
<resource>META-INF/cxf/bus-extensions.xml</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>Central Repository</name>
<url>http://repo.maven.apache.org/maven2</url>
</repository>
<repository>
<id>moss-forums</id>
<url>http://forum-mosstest.rhcloud.com/repository/</url>
</repository>
</repositories>
<<<<<<< HEAD
=======
<pluginRepositories>
<pluginRepository>
<id>codehaus-mojo-staging</id>
<name>codehaus-mojo-staging</name>
<url>https://nexus.codehaus.org/content/groups/snapshots-group/</url>
</pluginRepository>
</pluginRepositories>
>>>>>>> netclient
<dependencies>
<dependency>
<groupId>org.lwjgl.lwjgl</groupId>
<artifactId>parent</artifactId>
<version>2.9.0</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,5 +1,5 @@
<root>
<item name='java.util.HashMap V put(K, V) 0'>
<annotation name='org.jetbrains.annotations.NonNls'/>
</item>
<root>
<item name='java.util.HashMap V put(K, V) 0'>
<annotation name='org.jetbrains.annotations.NonNls'/>
</item>
</root>

View File

@ -10,6 +10,8 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: jme3:jme3-lwjgl-niftygui: 3.1.0" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.9" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-math:2.2" level="project" />
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.1" level="project" />
@ -44,6 +46,7 @@
<orderEntry type="library" name="Maven: log4j:log4j:1.2.15" level="project" />
<orderEntry type="library" name="Maven: commons-io:commons-io:2.4" level="project" />
<orderEntry type="library" name="Maven: com.intellij:annotations:9.0.4" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.9" level="project" />
</component>
</module>

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
main.class=org.nodetest.servercore.EventProcessor

View File

@ -1 +0,0 @@
main.class=org.nodetest.common.ScriptEnv

View File

@ -1,8 +0,0 @@
build.xml.data.CRC32=23062b59
build.xml.script.CRC32=9ea92df2
build.xml.stylesheet.CRC32=28e38971@1.53.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=23062b59
nbproject/build-impl.xml.script.CRC32=3b7463a5
nbproject/build-impl.xml.stylesheet.CRC32=6ddba6b6@1.53.1.46

View File

@ -1,83 +0,0 @@
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
auxiliary.org-netbeans-modules-projectimport-eclipse-core.key=src=src;file=lib/commons-cli-1.2.jar;file=lib/js-14.jar;file=lib/commons-cli-1.2-sources.jar;file=lib/db4o-8.0.249.16098-all-java5.jar;output=bin;
auxiliary.org-netbeans-modules-projectimport-eclipse-core.project=.
auxiliary.org-netbeans-modules-projectimport-eclipse-core.timestamp=1370875172897
auxiliary.org-netbeans-modules-projectimport-eclipse-core.workspace=C:\\Users\\Alexander\\workspace
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}/MossTest.jar
dist.javadoc.dir=${dist.dir}/javadoc
excludes=
file.reference.commons-cli-1.2-sources.jar=lib/commons-cli-1.2-sources.jar
file.reference.commons-cli-1.2.jar=lib/commons-cli-1.2.jar
file.reference.db4o-8.0.249.16098-all-java5.jar=lib/db4o-8.0.249.16098-all-java5.jar
file.reference.js-14.jar=lib/js-14.jar
file.reference.mosstest-src=src
includes=**
jar.compress=false
javac.classpath=\
${file.reference.commons-cli-1.2.jar}:\
${file.reference.js-14.jar}:\
${file.reference.commons-cli-1.2-sources.jar}:\
${file.reference.db4o-8.0.249.16098-all-java5.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=
manifest.file=manifest.mf
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
source.reference.commons-cli-1.2.jar=lib/commons-cli-1.2-sources.jar
src.dir=${file.reference.mosstest-src}

View File

@ -1,13 +0,0 @@
<?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>MossTest</name>
<source-roots>
<root id="src.dir" name="src"/>
</source-roots>
<test-roots/>
</data>
</configuration>
</project>

35
pom.xml
View File

@ -19,7 +19,15 @@
<id>moss-forums</id>
<url>http://forum-mosstest.rhcloud.com/repository/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>codehaus-mojo-staging</id>
<name>codehaus-mojo-staging</name>
<url>https://nexus.codehaus.org/content/groups/snapshots-group/</url>
</pluginRepository>
</pluginRepositories>
<build>
<testSourceDirectory>tests</testSourceDirectory>
<sourceDirectory>src</sourceDirectory>
@ -32,6 +40,28 @@
</resource>
</resources>
<plugins>
<!-- DEB plugin -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>deb-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<configuration>
<description>An open-source voxel game created in Java</description>
<maintainer>hexafraction &lt;hexafraction@gmail.com&gt;</maintainer>
<section>games</section>
<priority>optional</priority>
<architecture>all</architecture>
</configuration>
<executions>
<execution>
<phase>package</phase>
<!--<goals>
<goal>deb</goal>
</goals>-->
</execution>
</executions>
</plugin>
<!-- End DEB plugin -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
@ -336,6 +366,11 @@
<artifactId>annotations</artifactId>
<version>9.0.4</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,135 @@
package net.mosstest.client;
import net.mosstest.netcommand.MalformedPacketException;
import net.mosstest.netcommand.ToClientAuthDenied;
import net.mosstest.netcommand.ToClientAuthRequested;
import net.mosstest.servercore.MossNetPacket;
import net.mosstest.servercore.MosstestFatalDeathException;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.text.MessageFormat;
/**
* Created by hexafraction on 4/27/14.
*/
public class ClientDispatcher {
public static final byte[] EMPTY_PAYLOAD = {};
private MossClient client;
private boolean hasAuthed, hasBootstrapped;
private static final Logger logger = Logger.getLogger(ClientDispatcher.class);
public void dispatch(MossNetPacket inbound) {
this.dispatch0(inbound);
}
private void dispatch0(MossNetPacket inbound) {
switch (inbound.commandId) {
case 0x01: //TOCLIENT_AUTH_REQUESTED
handleAuthRequested(inbound);
break;
case 0x03: //TOCLIENT_AUTH_DENIED
handleAuthDenied(inbound);
break;
case 0x00: //SYS_NOP
case 0xFE: //SYS_BIND_CODE
case 0xFF: //SYS_QUENCH
// fall-through for packets already handled at a lower level
break;
default:
logger.warn(Messages.getString("PACKET_NOT_DISPATCHABLE"));
}
}
private void handleAuthDenied(MossNetPacket inbound) {
try {
ToClientAuthDenied parsed = new ToClientAuthDenied(inbound.payload);
switch (parsed.getReason()) {
case REASON_UNKNWN:
logger.fatal(Messages.getString("AUTH_FAILED_UNKNWN"));
break;
case REASON_BAD_PASS:
logger.fatal(Messages.getString("AUTH_FAILED_BAD_PASS"));
break;
case REASON_BANNED:
logger.fatal(Messages.getString("AUTH_FAILED_BAN"));
break;
case REASON_PLAYER_LIMIT:
logger.fatal(Messages.getString("AUTH_FAILED_PLAYER_LIM"));
break;
case REASON_LOGON_HOUR:
logger.fatal(Messages.getString("AUTH_FAILED_LOGON_HOUR"));
break;
case REASON_NO_NEW_PLAYERS:
logger.fatal(Messages.getString("AUTH_FAILED_NO_REGISTER"));
break;
case REASON_VERSION_MISMATCH:
logger.fatal(Messages.getString("AUTH_FAILED_VERSION"));
break;
case REASON_AUTH_TIMED_OUT:
logger.fatal(Messages.getString("AUTH_FAILED_TIMEOUT"));
break;
case REASON_SERVER_MAINT:
logger.fatal(Messages.getString("AUTH_FAILED_MAINTENANCE"));
break;
case REASON_FAILED_CONNECTION:
logger.fatal(Messages.getString("AUTH_FAILED_CONN"));
break;
}
throw new MosstestFatalDeathException(Messages.getString("AUTH_FAIL_EXCEPTION"));
} catch (IOException e) {
logger.fatal(Messages.getString("IOEXCEPTION_DESERIALIZE_AUTH_FAIL_PCKT"));
throw new MosstestFatalDeathException(e);
}
}
private void handleAuthRequested(MossNetPacket inbound) {
if (hasAuthed) {
logger.error(Messages.getString("ALREADY_AUTHED"));
return;
}
try {
ToClientAuthRequested parsed = new ToClientAuthRequested(inbound.payload);
authenticate(parsed);
} catch (IOException e) {
logger.fatal(Messages.getString("IOEXCEPTION_DESERIALIZE_AUTH_PCKT"));
throw new MosstestFatalDeathException(e);
} catch (MalformedPacketException e) {
logger.warn(Messages.getString("MALFORMED_TC_AUTH_REQUESTED"));
}
}
private void authenticate(ToClientAuthRequested parsed) throws IOException {
byte[] pass = client.getPassword();
switch (parsed.getAuthType()) {
case AUTH_NIL:
logger.warn(Messages.getString("SVR_NO_AUTH"));
client.net.sendPacket(new MossNetPacket(0x02, EMPTY_PAYLOAD));
case AUTH_PLAIN:
logger.warn(Messages.getString("SVR_AUTH_PLAIN"));
// FIXME some sort of confirmation dialog
client.net.sendPacket(new MossNetPacket(0x02, pass));
case AUTH_HASH_SHA512:
client.net.sendPacket(new MossNetPacket(0x02, DigestUtils.sha512(
ArrayUtils.addAll(
ArrayUtils.addAll(
client.getUsername().getBytes(), pass), parsed.getAuthParam()
)
)
)
);
case AUTH_CHALLENGE_RESPONSE:
logger.fatal(Messages.getString("SERVER_AUTH_CHALLENGE_RESP"));
throw new MosstestFatalDeathException(Messages.getString("AUTH_CHAP_FAILED"));
}
}
}

View File

@ -1,5 +1,9 @@
package net.mosstest.servercore;
package net.mosstest.client;
import net.mosstest.servercore.ClientManager;
import net.mosstest.servercore.CommonNetworking;
import net.mosstest.servercore.Messages;
import net.mosstest.servercore.MossNetPacket;
import org.apache.log4j.Logger;
import java.io.*;
@ -24,6 +28,8 @@ public class ClientNetworkingManager {
public static final int PACKET_QUEUE_CAPACITY = 1024;
public static final int TIME_TO_KEEPALIVE = 4000;
public static final byte[] EMPTY_PAYLOAD = new byte[]{};
public static final MossNetPacket QUENCH_PACKET = new MossNetPacket(CMD_QUENCH, EMPTY_PAYLOAD, true, true, true);
/**
* The logger.
*/
@ -125,7 +131,7 @@ public class ClientNetworkingManager {
* performance
*/
/**
* The packets.
* The packet receive queue
*/
public ArrayBlockingQueue<MossNetPacket> packets = new ArrayBlockingQueue<>(
PACKET_QUEUE_CAPACITY);
@ -351,7 +357,7 @@ public class ClientNetworkingManager {
this.bulkReadHandler.start();
this.fastReadHandler.start();
this.dgramReadHandler.start();
/* The send queue thread. */
/* The send queue thread. */
Thread sendQueueThread = new Thread(new Runnable() {
@Override
@ -433,7 +439,13 @@ public class ClientNetworkingManager {
ClientNetworkingManager.this.lastUdpOut
.get(),
ClientNetworkingManager.this.quenchedSince
.get())))))));
.get()
)
)
)
)
)
));
} catch (InterruptedException e) {
// pass
}
@ -451,25 +463,23 @@ public class ClientNetworkingManager {
* @param seqnum the seqnum
*/
protected void sendAck(int seqnum) {
// TODO Auto-generated method stub
logger.error("UDP acks are not supported at this time.");
}
/**
* Send tos udp conn.
*/
protected void sendTosUdpConn() {
// TODO Auto-generated method stub
logger.error("UDP connections are not supported at this time.");
}
/**
* Send quench.
* Send QUENCH_PACKET.
*/
protected void sendQuench() {
protected void sendQuench() throws IOException {
// TODO Sends a request for the server to back off with data and skip
// non-essential data.
this.sendPacket(QUENCH_PACKET);
}
/**

View File

@ -0,0 +1,49 @@
package net.mosstest.client;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
// TODO: Auto-generated Javadoc
/**
* The Class Messages.
*/
public class Messages {
/** The Constant BUNDLE_NAME. */
private static final String BUNDLE_NAME = "net.mosstest.client.messages"; //$NON-NLS-1$
/** The res bundle. */
private static ResourceBundle resBundle = ResourceBundle
.getBundle(BUNDLE_NAME);
/**
* Change language.
*
* @param identifier the identifier
*/
public static void changeLanguage(Locale identifier) {
resBundle = ResourceBundle.getBundle(BUNDLE_NAME, identifier);
}
/**
* Instantiates a new messages.
*/
private Messages() {
}
/**
* Gets the string.
*
* @param key the key
* @return the string
*/
public static String getString(String key) {
try {
return resBundle.getString(key);
} catch (MissingResourceException e) {
return '!' + key + '!';
}
}
}

View File

@ -0,0 +1,80 @@
package net.mosstest.client;
import net.mosstest.netcommand.ToServerHello;
import net.mosstest.scripting.MossScriptEnv;
import net.mosstest.scripting.NodePosition;
import net.mosstest.scripting.Player;
import net.mosstest.servercore.MossNetPacket;
import net.mosstest.servercore.MosstestSecurityManager;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
/**
* Created by hexafraction on 4/26/14.
*/
public class MossClient {
public static final short PROTOCOL_VERSION = 1;
private String username;
RemoteFileManager fileManager;
ClientNetworkingManager net;
private byte[] password;
public ClientState getState() {
return state;
}
private volatile ClientState state;
private Player ownPlayer;
private ClientDispatcher dispatcher;
public MossClient(String remoteHost, int port, String username, byte[] pass) throws IOException, InterruptedException {
this.username = username;
this.password = pass;
this.state = ClientState.PREPARING;
this.fileManager = RemoteFileManager.getInstance();
this.state = ClientState.CONNECTING;
this.fileManager.setClient(this);
this.net = new ClientNetworkingManager(remoteHost, port, false); // so far no UDP
// we need to send the hello to kick things off
this.net.sendPacket(new MossNetPacket(0x01, new ToServerHello(username, PROTOCOL_VERSION, MossScriptEnv.MIN_SCRIPT_API_VERSION, MossScriptEnv.MAX_SCRIPT_API_VERSION).toByteArray()));
}
public byte[] getPassword() {
SecurityManager sm = System.getSecurityManager();
if (sm instanceof MosstestSecurityManager) {
((MosstestSecurityManager) sm).checkMosstestControl();
}
return password;
}
public void setPassword(byte[] password) {
this.password = password;
}
public String getUsername() {
return username;
}
public enum ClientState {
PREPARING,
CONNECTING,
BUILDING_FILE_LIST,
FETCHING_FILES,
EXECUTING_STARTUP_SCRIPTS,
RENDERER_STARTING,
PLAYING,
CRASHED,
TIMED_OUT
}
}

View File

@ -0,0 +1,281 @@
package net.mosstest.client;
import com.jme3.asset.*;
import net.mosstest.servercore.*;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.log4j.Logger;
import java.io.*;
import java.nio.ByteBuffer;
import java.security.NoSuchAlgorithmException;
import java.text.MessageFormat;
import java.util.*;
/**
* Created by hexafraction on 4/26/14.
*/
public class RemoteFileManager implements IFileManager {
private static final String XML_DEPENDENCY_KEY = "dependencies.dependency";
private static volatile RemoteFileManager instance = null;
private HashSet<String> visitedScripts;
protected HashSet<AbstractMossScript> executed = new HashSet<>();
public static RemoteFileManager getInstance() {
if (instance == null) {
synchronized (RemoteFileManager.class) {
if (instance == null) {
instance = new RemoteFileManager();
}
}
}
return instance;
}
private static final Logger logger = Logger.getLogger(RemoteFileManager.class);
private HashMap<String, RemoteFile> knownByName = new HashMap<>();
private HashMap<String, RemoteFile> knownByHash = new HashMap<>();
private File cacheBasedir = new File("cache");
// used to request files
private MossClient client;
public void setClient(MossClient client) {
this.client = client;
}
@Override
public RemoteFile getFile(String name) throws IOException {
return knownByName.get(name);
}
@Override
public void registerFile(String name, String sha256, long size) throws IOException {
logger.info(MessageFormat.format("Registered {0} with hash {1}, and a size of {2} bytes", name, sha256, size));
RemoteFile rmf = new RemoteFile(sha256, name, size);
knownByName.put(name, rmf);
knownByHash.put(sha256, rmf);
}
@Override
public void receiveFileChunk(String sha256, int chunkId, ByteBuffer buf) throws IOException {
RemoteFile rmf = this.knownByHash.get(sha256);
if (rmf == null) {
logger.warn(MessageFormat.format("The server tried to send a file chunk for a file with hash {0} that we don't know about.", sha256));
return;
}
rmf.writeChunk(chunkId, buf.array());
}
@Override
public Class<? extends AssetLocator> getAssetLocatorClass() {
return RemoteAssetLocator.class;
}
@Override
public List<? extends IMossFile> getFiles() {
return null;
}
@Override
public AbstractMossScript getScript(String name) throws IOException, MossWorldLoadException {
List<AbstractMossScript> dependencies = new ArrayList<>();
try {
File scriptXml = this.getFile(name + "/script.xml").file;
XMLConfiguration scriptCfg = new XMLConfiguration(scriptXml);
String[] scNames = scriptCfg.getStringArray(XML_DEPENDENCY_KEY);
for (String sc : scNames) {
if (sc.equals(name)) continue;
if (visitedScripts.contains(sc)) {
logger.fatal(MessageFormat.format(Messages.getString("CIRCULAR_DEPENDENCY_ISSUE"), name, sc));
throw new MossWorldLoadException(MessageFormat.format(Messages.getString("CIRCULAR_DEPENDENCY_ISSUE"), name, sc));
}
try {
dependencies.add(this.getScript(sc));
} catch (StackOverflowError e) {
// should never happen
logger.fatal(Messages.getString("DEPFIND_STACK_OVERFLOW"));
throw new MossWorldLoadException("FIXME The stack overflowed while resolving dependencies. Either there is an undetected dependency issue, or there is simply an extreme number of dependencies.");
}
}
} catch (ConfigurationException | FileNotFoundException e) {
logger.warn(Messages.getString("SCRIPT_XML_MISSING"));
}
return new RemoteScript(name, dependencies);
}
public class RemoteFile implements IMossFile {
private final long size;
private final File file;
private final RandomAccessFile rFile;
private final BitSet completedChunks;
private final String sha256;
private final int numChunks;
private final String name;
RemoteFile(String sha256, String name, long size) throws IOException {
this.sha256 = sha256;
this.name = name;
numChunks = (int) Math.ceil(size / IMossFile.CHUNK_SIZE);
if (!sha256.matches("[0-9A-Za-z]{32}"))
throw new MosstestFatalDeathException("A file SHA256 was invalid, and could not be used for caching.");
this.file = new File(RemoteFileManager.this.cacheBasedir, sha256);
this.file.createNewFile();
this.rFile = new RandomAccessFile(this.file, "rw");
this.size = size;
try {
completedChunks = new BitSet(numChunks);
String actualSha = IFileManager.getHash(file);
if (actualSha.equalsIgnoreCase(sha256)) {
completedChunks.set(0, numChunks);
}
} catch (NoSuchAlgorithmException e) {
throw new MosstestFatalDeathException("The SHA-256 algorithm could not be found, but is required to cache files.");
}
}
@Override
public Reader getReader() throws FileNotFoundException {
return new FileReader(this.file);
}
@Override
public InputStream getInputStream() throws FileNotFoundException {
return new FileInputStream(this.file);
}
@Override
public byte[] readChunk(int chunkId) throws IOException {
this.rFile.seek(chunkId * IMossFile.CHUNK_SIZE);
byte[] buf = new byte[(int) (chunkId == (this.numChunks - 1) ? (this.size % IMossFile.CHUNK_SIZE)
: IMossFile.CHUNK_SIZE)];
this.rFile.readFully(buf);
return buf;
}
@Override
public void writeChunk(int chunkId, byte[] buf) throws IOException {
this.rFile.seek(chunkId * IMossFile.CHUNK_SIZE);
if (((chunkId == (this.numChunks - 1) ? (this.size % IMossFile.CHUNK_SIZE) : IMossFile.CHUNK_SIZE)) != buf.length)
throw new MosstestFatalDeathException(MessageFormat.format("An inbound chunk for file {0} is not of the correct size. The server may be sending erroneous data.", this.name));
this.completedChunks.set(chunkId);
if (isComplete()) {
logger.info(MessageFormat.format("Completed file {0}.", this.name));
}
try {
String realHash = IFileManager.getHash(this.file);
if (!this.sha256.equalsIgnoreCase(realHash)) {
logger.warn(MessageFormat.format("File {0} expected with hash {1} but got reassembled as hash {2}", this.name, this.sha256, realHash));
}
} catch (NoSuchAlgorithmException e) {
throw new MosstestFatalDeathException("The SHA-256 algorithm could not be found, but is required to cache files.");
}
}
@Override
public String getSha256() {
return this.sha256;
}
@Override
public String getName() {
return this.name;
}
@Override
public boolean isComplete() {
return (completedChunks.nextClearBit(0) == -1 || completedChunks.nextClearBit(0) == this.numChunks);
}
@Override
public long getSize() {
return this.size;
}
}
private static class RemoteAssetLocator implements AssetLocator {
private static final Logger logger = Logger.getLogger(RemoteAssetLocator.class);
@Override
public void setRootPath(String s) {
// ignore
logger.warn(MessageFormat.format("Tried to set root path {0} for RemoteAssetLocator, which ignores the root path.", s));
}
@Override
public AssetInfo locate(AssetManager assetManager, AssetKey assetKey) {
try {
return new RemoteAssetInfo(assetManager, assetKey,
RemoteFileManager.getInstance().getFile(assetKey.getName()));
} catch (IOException ex) {
throw new AssetLoadException("Failed to open file: "
+ assetKey.getName(), ex);
}
}
private static class RemoteAssetInfo extends AssetInfo {
private RemoteFile file;
public RemoteAssetInfo(AssetManager manager, AssetKey key, RemoteFile file) {
super(manager, key);
this.file = file;
}
@Override
public InputStream openStream() {
try {
return this.file.getInputStream();
} catch (IOException ex) {
throw new AssetLoadException("Failed to open file: "
+ this.file.getName(), ex);
}
}
}
}
private class RemoteScript extends AbstractMossScript {
private final List<AbstractMossScript> dependencies;
public RemoteScript(String name, List<AbstractMossScript> dependencies) {
super(name);
this.dependencies = dependencies;
}
@Override
public void exec(ScriptEnv sEnv) throws IOException, MossWorldLoadException {
RemoteFileManager.this.executed.add(this);
for (AbstractMossScript sc : dependencies) {
sc.exec(sEnv);
}
sEnv.runScript(this.getInitFile());
}
@Override
public IMossFile getInitFile() throws IOException {
return RemoteFileManager.this.getFile(this.name + "/init.js");
}
@Override
public List<AbstractMossScript> getDependencies() {
return Collections.unmodifiableList(dependencies);
}
}
}

View File

@ -0,0 +1,20 @@
IOEXCEPTION_DESERIALIZE_AUTH_PCKT=IOException deserializing an authentication packet, or sending its reply.
IOEXCEPTION_DESERIALIZE_AUTH_FAIL_PCKT=IOException deserializing an authentication failure packet, or sending its reply.
AUTH_FAILED_UNKNWN=Authentication failed for an unknown reason
AUTH_FAILED_BAD_PASS=Authentication failed due to a bad password.
AUTH_FAILED_BAN=You are banned.
AUTH_FAILED_PLAYER_LIM=The server is at its player limit; no more players can join.
AUTH_FAILED_LOGON_HOUR=A server reports a logon hour restriction. The meaning of this may depend as Mosstest does not use this type of failure in its default implementation
AUTH_FAILED_NO_REGISTER=The server is not allowing new players to register.
AUTH_FAILED_VERSION=The server and client versions do not match and no common version can be negotiated upon.
AUTH_FAILED_TIMEOUT=Authentication has timed out
AUTH_FAILED_MAINTENANCE=The server is undergoing maintenance. Generally, only administrators can join in such a case
AUTH_FAILED_CONN=The connection failed; cannot authenticate
ALREADY_AUTHED=Server request authentication, but we've already authenticated. Throwing away request for security.
SVR_NO_AUTH=Server is not using authentication...
SVR_AUTH_PLAIN=Server is requesting password in plain text.
SERVER_AUTH_CHALLENGE_RESP=Challenge-response authentication is not supported at this time.
AUTH_CHAP_FAILED=Challenge-Response auth unsupported
MALFORMED_TC_AUTH_REQUESTED=Malformed TOCLIENT_AUTH_REQUESTED packet.
PACKET_NOT_DISPATCHABLE=Received a packet that cannot be dispatched at this time.
AUTH_FAIL_EXCEPTION=Server denied authentication; client cannot continue

View File

@ -0,0 +1,51 @@
GUIBugReportDialog.DLG_BUG_DESC=Descrizione dettagliata del problema\:
GUIBugReportDialog.DLG_BUG_DESC_DEFAULT=Per favore descrivete qui il vostro problema, preferibilmente includendo quello che vi aspettavate che succedesse, che cosa \u00E8 successo, e qualsiasi altro dettaglio riguardante il mondo o il gioco.\n\nPer favore tenete presente che non possiamo aiutarvi con giochi o mod di terze parti.
GUIBugReportDialog.DLG_BUG_EMAIL=e-mail (facoltativa)\:
GUIBugReportDialog.DLG_BUG_NAME=Nome\:
GUIBugReportDialog.DLG_BUG_SUMMARY=Riassunto del problema\:
GUIBugReportDialog.DLG_BUG_TITLE=Segnalare un bug
GUIBugReportDialog.DLG_CHECKBOX_INCLUDE_TECH_INFO=Includere informazioni tecniche
GUIBugReportDialog.DLG_CXL=Annullare
GUIBugReportDialog.DLG_OK=OK
GUIBugReportDialog.DLG_SUBMIT=Inviare
GUIBugReportDialog.NOTICE_INFO_INCLUDED=Se questa casella viene marcata verranno aggiunte alla segnalazione del bug le seguenti informazioni\: \n\n
GUIClientsideLauncher.23=Segnalare un bug...
GUIClientsideLauncher.24=Richiedere una caratteristica nuova...
GUIClientsideLauncher.25=Visitare il sito web
GUIClientsideLauncher.26=Progetto GitHub
GUIClientsideLauncher.27=Visitare i forum
GUIClientsideLauncher.COL_GAME_PRESET=Gioco preimpostato
GUIClientsideLauncher.COL_WORLD_DESC=Descrizione
GUIClientsideLauncher.COL_WORLD_NAME=Nome del mondo
GUIClientsideLauncher.DLG_ABOUT=Informazioni
GUIClientsideLauncher.DLG_DELETE=Cancellare...
GUIClientsideLauncher.DLG_NEW=Nuovo...
GUIClientsideLauncher.DLG_NO_WORLD_TO_DELETE=Non \u00E8 stato scelto nessun mondo da cancellare. Per favore selezionate un mondo esistente nella tabella.
GUIClientsideLauncher.DLG_PLAY=Giocare
GUIClientsideLauncher.DLG_SETTINGS=Impostazioni...
GUIClientsideLauncher.DLG_SINGLEPLAYER=Giocatore singolo
GUIClientsideLauncher.DLG_TITLE=Avviatore del Client Mosstest <0.0.1-initial>
GUIClientsideLauncher.ERR_NO_WORLD_SELECTED=Non \u00E8 stato selezionato nessun mondo da avviare. Per favore selezionate un mondo esistente nella tabella, o create un mondo nuovo.
GUIClientsideLauncher.ERR_NO_WORLD_SELECTED_TITLE=Nessun mondo selezionato
GUIClientsideLauncher.NOTICE_DEFAULT_GAME_CODE=Il codice e le immagini predefinite del gioco sono state create da dolinksy296, hexafraction, e altri.\n
GUIClientsideLauncher.NOTICE_PRIMARY_AUTHORS=Creato da hexafraction, thatnerd2, e altri.\n
GUIClientsideLauncher.NOTICE_TOOLS_USED=Creato con l'aiuto di Eclipse, Git, Maven e innumerevoli servizi come TravisCI e GitHub.\n
GUIClientsideLauncher.SYS_NEWLINE=\n
GUIClientsideLauncher.USES_LIBS=Utilizza le librerie seguenti\:\n
GUIClientsideLauncher.WARN_SET_LAF=Avviso\: l'aspetto non pu\u00F2 essere applicato al sistema. Si utilizza l'aspetto predefinito.
GUIWorldCreationDialog.CXL=Annullare
GUIWorldCreationDialog.DLG_TITLE=Creare un nuovo mondo per giocatore singolo...
GUIWorldCreationDialog.GAME_PROFILE=Profilo di gioco\:
GUIWorldCreationDialog.OK=OK
GUIWorldCreationDialog.WORLD_DESC=Descrizione\:
GUIWorldCreationDialog.WORLD_NAME=Nome del mondo\:
GUIWorldDeletionDialog.AREYOUSURE_TEXT=Siete certi di volere cancellare {0}? Ci\u00F2 non pu\u00F2 essere annullato.
GUIWorldDeletionDialog.DLG_TITLE=Cancellare un mondo per giocatore singolo...
GUIWorldDeletionDialog.NO=No
GUIWorldDeletionDialog.QUESTIONMARK_CANNOT_UNDO=? Questa operazione non pu\u00F2 essere annullata.
GUIWorldDeletionDialog.YES=S\u00EC
GAMEPLAY_NO_WORLD=Si \u00E8 tentato di avviare il gioco senza selezionare un mondo.
GAME_UNCAUGHT_EXCEPT=Eccezione non notata nel codice del gioco, apertura del segnalatore di bug.
STACKTRACE_WRITTEN=Lo stack trace \u00E8 stato scritto su {0}
WORLD_CREATION_CXLD=Creazione del mondo annullata
NO_WORLD_TO_DELETE=Si \u00E8 tentato di cancellare un mondo, ma non ne \u00E8 stato selezionato nessuno.

View File

@ -1,4 +1,4 @@
package net.mosstest.servercore.netcommand;
package net.mosstest.netcommand;
/**
* The Class MalformedPacketException.

View File

@ -0,0 +1,113 @@
package net.mosstest.netcommand;
import java.io.*;
/**
* Created by hexafraction on 5/3/14.
*/
public class ToClientAuthDenied extends ToClientCommand {
public enum DenyReason {
REASON_UNKNWN,
REASON_BAD_PASS,
REASON_BANNED,
REASON_PLAYER_LIMIT,
REASON_LOGON_HOUR,
REASON_NO_NEW_PLAYERS,
REASON_VERSION_MISMATCH,
REASON_AUTH_TIMED_OUT,
REASON_SERVER_MAINT,
REASON_FAILED_CONNECTION
}
public DenyReason getReason() {
return reason;
}
private final DenyReason reason;
public ToClientAuthDenied(DenyReason reason) {
this.reason = reason;
}
public ToClientAuthDenied(byte[] buf) throws IOException {
ByteArrayInputStream bs = new ByteArrayInputStream(buf);
DataInputStream ds = new DataInputStream(bs);
int reason_ = ds.readUnsignedByte();
switch(reason_){
case 0x01:
this.reason = DenyReason.REASON_BAD_PASS;
break;
case 0x02:
this.reason = DenyReason.REASON_BANNED;
break;
case 0x03:
this.reason = DenyReason.REASON_PLAYER_LIMIT;
break;
case 0x04:
this.reason = DenyReason.REASON_LOGON_HOUR;
break;
case 0x05:
this.reason = DenyReason.REASON_NO_NEW_PLAYERS;
break;
case 0x06:
this.reason = DenyReason.REASON_PLAYER_LIMIT;
break;
case 0x07:
this.reason = DenyReason.REASON_VERSION_MISMATCH;
break;
case 0x08:
this.reason = DenyReason.REASON_AUTH_TIMED_OUT;
break;
case 0x09:
this.reason = DenyReason.REASON_SERVER_MAINT;
break;
case 0x0a:
this.reason = DenyReason.REASON_FAILED_CONNECTION;
break;
// fall through for unknwn
case 0x00:
default:
this.reason = DenyReason.REASON_UNKNWN;
}
}
public byte[] toByteArray() throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
switch (this.reason) {
case REASON_UNKNWN:
dos.writeByte(0x00);
break;
case REASON_BAD_PASS:
dos.writeByte(0x01);
break;
case REASON_BANNED:
dos.writeByte(0x02);
break;
case REASON_PLAYER_LIMIT:
dos.writeByte(0x03);
break;
case REASON_LOGON_HOUR:
dos.writeByte(0x04);
break;
case REASON_NO_NEW_PLAYERS:
dos.writeByte(0x06);
break;
case REASON_VERSION_MISMATCH:
dos.writeByte(0x07);
break;
case REASON_AUTH_TIMED_OUT:
dos.writeByte(0x08);
break;
case REASON_SERVER_MAINT:
dos.writeByte(0x09);
break;
case REASON_FAILED_CONNECTION:
dos.writeByte(0x0a);
break;
}
return bos.toByteArray();
}
}

View File

@ -1,5 +1,5 @@
//just keep the same package and import lines
package net.mosstest.servercore.netcommand;
package net.mosstest.netcommand;
import java.io.*;
@ -26,7 +26,7 @@ public class ToClientAuthRequested extends ToClientCommand {
/**
* The Enum AuthType.
*/
enum AuthType {
public enum AuthType {
/**
* The auth nil.
@ -144,4 +144,12 @@ public class ToClientAuthRequested extends ToClientCommand {
//Use this line at the end to finish up
return bos.toByteArray();
}
public AuthType getAuthType() {
return authType;
}
public byte[] getAuthParam() {
return authParam;
}
}

View File

@ -1,4 +1,4 @@
package net.mosstest.servercore.netcommand;
package net.mosstest.netcommand;
/**
* The Class ToClientCommand.

View File

@ -0,0 +1,10 @@
package net.mosstest.netcommand;
/**
* The Class ToServerCommand.
*/
public abstract class ToServerCommand {
//ignore
}

View File

@ -0,0 +1,43 @@
package net.mosstest.netcommand;
import java.io.*;
/**
* Created by hexafraction on 4/27/14.
*/
public class ToServerHello {
private final String username;
private final int protocolVersion;
private final int minScriptApi;
private final int maxScriptApi;
public ToServerHello(byte[] buf) throws IOException,
MalformedPacketException {
// constructor from byte[] is parsing
// Keep lines below for all of these tasks
ByteArrayInputStream bs = new ByteArrayInputStream(buf);
DataInputStream ds = new DataInputStream(bs);
this.protocolVersion = ds.readUnsignedShort();
this.minScriptApi = ds.readUnsignedShort();
this.maxScriptApi = ds.readUnsignedShort();
this.username = ds.readUTF();
}
public ToServerHello(String username, int protocolVersion, int minScriptApi, int maxScriptApi) {
this.username = username;
this.protocolVersion = protocolVersion;
this.minScriptApi = minScriptApi;
this.maxScriptApi = maxScriptApi;
}
public byte[] toByteArray() throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeShort(this.protocolVersion);
dos.writeShort(this.minScriptApi);
dos.writeShort(this.maxScriptApi);
dos.writeUTF(this.username);
return bos.toByteArray();
}
}

View File

@ -1,3 +1,4 @@
package net.mosstest.scripting;
import net.mosstest.scripting.events.IMossEvent;
@ -37,11 +38,27 @@ import java.util.List;
* @since 0.0
*/
public class MossScriptEnv {
public static final short SCRIPT_API_VERSION = 1;
public static final short MIN_SCRIPT_API_VERSION = 1;
public static final short MAX_SCRIPT_API_VERSION = 1;
public void registerNodeChangeHandler(MossNodeChangeHandler h) {
}
private InheritableThreadLocal<Short> requestedScriptApiVer = new InheritableThreadLocal<Short>(){
@Override
protected Short initialValue() {
return MAX_SCRIPT_API_VERSION;
}
};
public void setRequestedScriptApiVer(short requestedScriptApiVer) {
if(requestedScriptApiVer >= MIN_SCRIPT_API_VERSION && requestedScriptApiVer <= MAX_SCRIPT_API_VERSION)
this.requestedScriptApiVer.set(requestedScriptApiVer);
else {
throw new MosstestFatalDeathException("A plugin requests an unsatisfiable script API version.");
}
}
private HashMap<Class<? extends IMossEvent>, ArrayList<MossEventHandler>> eventHandlers;
@ -315,13 +332,13 @@ public class MossScriptEnv {
return this.fp;
}
private HashMap<Class<? extends IMossEvent>, List<MossEventHandler>> handlers = new HashMap<>();
private HashMap<Class<? extends IMossEvent>, List<WrappedHandler>> handlers = new HashMap<>();
public List<MossEventHandler> getEventHandlers(
public List<WrappedHandler> getEventHandlers(
Class<? extends IMossEvent> clazz) {
List<MossEventHandler> l = Collections.unmodifiableList(handlers.get(clazz));
List<WrappedHandler> l = Collections.unmodifiableList(handlers.get(clazz));
if (l == null) {
handlers.put(clazz, new ArrayList<MossEventHandler>());
handlers.put(clazz, new ArrayList<WrappedHandler>());
return Collections.EMPTY_LIST;
}
return l;
@ -329,14 +346,12 @@ public class MossScriptEnv {
}
public void registerHandler(MossEventHandler handler, Class<? extends IMossEvent> clazz) {
List<MossEventHandler> l = handlers.get(clazz);
List<WrappedHandler> l = handlers.get(clazz);
if (l == null) {
l = new ArrayList<MossEventHandler>();
l = new ArrayList<WrappedHandler>();
handlers.put(clazz, l);
l.add(handler);
return;
}
l.add(handler);
l.add(new WrappedHandler(handler, this.requestedScriptApiVer.get()));
}

View File

@ -29,6 +29,8 @@ private static final Logger logger = Logger.getLogger(Player.class);
*/
private HashMap<String, MossInventory> inventories = new HashMap<>();
public int playerId;
/**
* The name.
*/

View File

@ -0,0 +1,23 @@
package net.mosstest.scripting;
import net.mosstest.scripting.handlers.MossEventHandler;
/**
* Created by hexafraction on 5/3/14.
*/
public class WrappedHandler {
private final MossEventHandler handler;
private final short requestedApiVer;
public WrappedHandler(MossEventHandler handler, short requestedApiVer) {
this.handler = handler;
this.requestedApiVer = requestedApiVer;
}
public MossEventHandler getHandler() {
return handler;
}
public short getRequestedApiVer() {
return requestedApiVer;
}
}

View File

@ -0,0 +1,2 @@
#This properties file describes game tidbits such as item names, materials, and other things a player might interact with. These are for modders' convenience.

View File

@ -0,0 +1,4 @@
AntiCheatController.THREAD_NAME=antitruffa
MossEvent.MSG_CROSS_DMZ_SECURITY_WARNING=Tentativo di accedere alle risorse controllate nello script DMZ.
ScriptableDatabase.DB_NAME_INVALID=Nome della banca dati non valido.
INV_IOEXCEPTION_FATAL=IOException durante la serializzazione di un inventario. IL MONDO CADRA' A BREVE.

View File

@ -1,3 +1,4 @@
package net.mosstest.servercore;
import java.io.IOException;
@ -10,12 +11,12 @@ public abstract class AbstractMossScript {
}
@org.jetbrains.annotations.NonNls
final String name;
abstract void exec(ScriptEnv sEnv) throws IOException, MossWorldLoadException;
protected final String name;
public abstract void exec(ScriptEnv sEnv) throws IOException, MossWorldLoadException;
abstract IMossFile getInitFile() throws IOException;
public abstract IMossFile getInitFile() throws IOException;
abstract List<AbstractMossScript> getDependencies();
public abstract List<AbstractMossScript> getDependencies();
@Override
public final boolean equals(Object o) {
@ -34,3 +35,4 @@ public abstract class AbstractMossScript {
return name.hashCode();
}
}

View File

@ -0,0 +1,60 @@
package net.mosstest.servercore;
import com.jme3.input.controls.ActionListener;
public class ActivityListener implements ActionListener {
private final float SPEED;
private float[] velocities;
public ActivityListener (float[] velocities, float speed) {
this.velocities = velocities;
SPEED = speed;
}
@Override
public void onAction(String name, boolean keyPressed, float tpf) {
if (name.equals("Jump") && keyPressed/* && jumpSPEED == 0 */) {
velocities[1] = 2f;
} else if (name.equals("Jump") && !keyPressed) {
velocities[1] = 0f;
}
if (name.equals("Down") && keyPressed) {
velocities[1] = -2f;
} else if (name.equals("Down") && !keyPressed) {
velocities[1] = 0f;
}
if (name.equals("Left") && keyPressed) {
velocities[0] = SPEED;
} else if (name.equals("Left") && !keyPressed
&& velocities[0] == SPEED) {
velocities[0] = 0;
}
if (name.equals("Right") && keyPressed) {
velocities[0] = -SPEED;
} else if (name.equals("Right") && !keyPressed
&& velocities[0] == -SPEED) {
velocities[0] = 0;
}
if (name.equals("Forward") && keyPressed) {
velocities[2] = SPEED;
} else if (name.equals("Forward") && !keyPressed
&& velocities[2] == SPEED) {
velocities[2] = 0;
}
if (name.equals("Back") && keyPressed) {
velocities[2] = -SPEED;
} else if (name.equals("Back") && !keyPressed
&& velocities[2] == -SPEED) {
velocities[2] = 0;
}
if (name.equals("TestFeature") && keyPressed) {
System.err.println("\nDEBUGGING FEATURE\n");
}
}
}

View File

@ -1,5 +1,6 @@
package net.mosstest.servercore;
import net.mosstest.client.ClientNetworkingManager;
import net.mosstest.scripting.Position;
// TODO: Auto-generated Javadoc

View File

@ -1,5 +1,7 @@
package net.mosstest.servercore;
import net.mosstest.client.ClientNetworkingManager;
import java.io.IOException;

View File

@ -7,11 +7,11 @@ package net.mosstest.servercore;
public class CommonNetworking {
/** The Constant magic. */
static final int magic=0xfa7d2e4a;
public static final int magic=0xfa7d2e4a;
/** The Constant magicNoAck. */
static final int magicNoAck=0xfa7d2e4f;
public static final int magicNoAck=0xfa7d2e4f;
/** The Constant magicAck. */
static final int magicAck=0xfa7d2740;
public static final int magicAck=0xfa7d2740;
}

View File

@ -1,8 +1,13 @@
package net.mosstest.servercore;
import com.jme3.scene.Node;
/**
* The Class DrawableHudset.
*/
public class DrawableHudset {
public Node getHudNode(){
return null;
}
}

View File

@ -1,9 +1,6 @@
package net.mosstest.servercore;
import net.mosstest.scripting.MapNode;
import net.mosstest.scripting.MossScriptEnv;
import net.mosstest.scripting.MossScriptException;
import net.mosstest.scripting.NodePosition;
import net.mosstest.scripting.*;
import net.mosstest.scripting.events.IMossEvent;
import net.mosstest.scripting.events.MossNodeChangeEvent;
import net.mosstest.scripting.events.ThreadStopEvent;
@ -27,9 +24,9 @@ import java.util.concurrent.atomic.AtomicInteger;
* The Class EventProcessor.
*
* @author rarkenin, hexafraction
* <p>
* <p/>
* Blargh.
* <p>
* <p/>
* This is a nasty thread pool. If you don't understand threading or
* Java well, you may want to stick to only accessing the queue as
* otherwise asphyxiation, drowning, or chlorine poisoning may occur.
@ -101,10 +98,10 @@ public class EventProcessor {
}
private void dispatchEvent(IMossEvent evt) {
List<MossEventHandler> evtHandlerList = this.ev
List<WrappedHandler> evtHandlerList = this.ev
.getEventHandlers(evt.getClass());
try {
for (MossEventHandler ourHandler : evtHandlerList) {
for (WrappedHandler ourHandler : evtHandlerList) {
if (dispatchEventInner(ourHandler, evt)) {
return;
}
@ -116,13 +113,16 @@ public class EventProcessor {
}
}
private boolean dispatchEventInner(MossEventHandler ourHandler,
private boolean dispatchEventInner(WrappedHandler wrappedHandler,
IMossEvent evt) throws IllegalArgumentException {
MossEventHandler ourHandler = wrappedHandler.getHandler();
try {
if (evt instanceof MossNodeChangeEvent) {
return ((MossNodeChangeHandler) ourHandler)
.onAction((MossNodeChangeEvent) evt);
{
this.ev.setRequestedScriptApiVer(wrappedHandler.getRequestedApiVer());
return ((MossNodeChangeHandler) ourHandler)
.onAction((MossNodeChangeEvent) evt);
}
} else
throw new IllegalArgumentException(
@ -174,7 +174,8 @@ public class EventProcessor {
processEvents();
}
});
}
);
threads[c].start();
EventProcessor.this.currentThreads.incrementAndGet();
@ -199,7 +200,8 @@ public class EventProcessor {
processEvents();
}
}).run();
}
).run();
EventProcessor.this.currentThreads
.incrementAndGet();
@ -221,11 +223,11 @@ public class EventProcessor {
}
}
}
}, Messages.getString("EventProcessor.THREAD_NAME_MGR"));
}, Messages.getString("EventProcessor.THREAD_NAME_MGR")
);
manager.start();
}
}

View File

@ -0,0 +1,138 @@
package net.mosstest.servercore;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public class FaceRenderer {
private static FloatBuffer vertices;
private static FloatBuffer textures;
private static FloatBuffer normals;
private static IntBuffer indices;
private static int vertexIndexCounter;
public static void initialize () {
vertices = getDirectFloatBuffer(950000);
textures = getDirectFloatBuffer(950000);
normals = getDirectFloatBuffer(950000);
indices = getDirectIntBuffer(950000);
vertexIndexCounter = 0;
}
public static boolean isFaceVisible (Face f, int[][][] nodes, byte i, byte j, byte k) {
switch (f) {
case FRONT:
if (k - 1 < 0 || nodes[i][j][k - 1] == 0) {
return true;
}
case TOP:
if (j + 1 >= nodes[i].length || nodes[i][j + 1][k] == 0) {
return true;
}
case BACK:
if (k + 1 >= nodes[i][j].length || nodes[i][j][k + 1] == 0) {
return true;
}
break;
case BOTTOM:
if (j - 1 < 0 || nodes[i][j - 1][k] == 0) {
return true;
}
break;
case LEFT:
if (i + 1 <= nodes.length || nodes[i + 1][j][k] == 0) {
return true;
}
break;
case RIGHT:
/*if (i - 1 < 0 || nodes[i - 1][j][k] == 0) {
return true;
}*/
break;
}
return false;
}
public static void populateBuffers(Face f, float x, float y, float z, final float NODE_SIZE) {
/*Vertices start at the top left corner and go clockwise around the face.*/
if (f == Face.FRONT) {
vertices.put(x).put(y).put(z);
vertices.put(x + NODE_SIZE).put(y).put(z);
vertices.put(x + NODE_SIZE).put(y).put(z - NODE_SIZE);
vertices.put(x).put(y).put(z - NODE_SIZE);
}
else if (f == Face.TOP) {
vertices.put(x).put(y + NODE_SIZE).put(z);
vertices.put(x + NODE_SIZE).put(y + NODE_SIZE).put(z);
vertices.put(x + NODE_SIZE).put(y).put(z);
vertices.put(x).put(y).put(z);
}
else if (f == Face.BACK) {
vertices.put(x + NODE_SIZE).put(y + NODE_SIZE).put(z);
vertices.put(x).put(y + NODE_SIZE).put(z);
vertices.put(x).put(y + NODE_SIZE).put(z - NODE_SIZE);
vertices.put(x + NODE_SIZE).put(y + NODE_SIZE).put(z - NODE_SIZE);
}
else if (f == Face.BOTTOM) {
vertices.put(x + NODE_SIZE).put(y + NODE_SIZE).put(z - NODE_SIZE);
vertices.put(x).put(y + NODE_SIZE).put(z - NODE_SIZE);
vertices.put(x).put(y).put(z - NODE_SIZE);
vertices.put(x + NODE_SIZE).put(y).put(z - NODE_SIZE);
}
else if (f == Face.LEFT) {
vertices.put(x).put(y + NODE_SIZE).put(z);
vertices.put(x).put(y).put(z);
vertices.put(x).put(y).put(z - NODE_SIZE);
vertices.put(x).put(y + NODE_SIZE).put(z - NODE_SIZE);
}
else if (f == Face.RIGHT) {
vertices.put(x + NODE_SIZE).put(y).put(z);
vertices.put(x + NODE_SIZE).put(y + NODE_SIZE).put(z);
vertices.put(x + NODE_SIZE).put(y + NODE_SIZE).put(z - NODE_SIZE);
vertices.put(x + NODE_SIZE).put(y).put(z - NODE_SIZE);
}
indices.put(vertexIndexCounter + 0).put(vertexIndexCounter + 2).put(vertexIndexCounter + 1);
indices.put(vertexIndexCounter + 0).put(vertexIndexCounter + 3).put(vertexIndexCounter + 2);
textures.put(0).put(0);
textures.put(0).put(1);
textures.put(1).put(1);
textures.put(1).put(0);
for(int m=0; m<4; m++)
normals.put(2).put(3).put(5);
vertexIndexCounter += 4;
}
public enum Face {
FRONT, TOP, BACK, BOTTOM, LEFT, RIGHT
}
private static FloatBuffer getDirectFloatBuffer (int size) {
ByteBuffer temp = ByteBuffer.allocateDirect(size);
return temp.asFloatBuffer();
}
private static IntBuffer getDirectIntBuffer (int size) {
ByteBuffer temp = ByteBuffer.allocateDirect(size);
return temp.asIntBuffer();
}
public static FloatBuffer getVertices () {
return vertices;
}
public static FloatBuffer getTextureCoordinates () {
return textures;
}
public static FloatBuffer getNormals () {
return normals;
}
public static IntBuffer getIndices () {
return indices;
}
}

View File

@ -2,16 +2,61 @@ package net.mosstest.servercore;
import com.jme3.asset.AssetLocator;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
public interface IFileManager {
static String getHash(File f) throws IOException,
NoSuchAlgorithmException, FileNotFoundException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
try (FileInputStream fis = new FileInputStream(f)) {
try (FileChannel fc = fis.getChannel()) {
ByteBuffer bbf = ByteBuffer.allocateDirect(LocalFileManager.HASHING_BUFFER_SIZE);
int bytesRead;
bytesRead = fc.read(bbf);
while ((bytesRead != -1) && (bytesRead != 0)) {
bbf.flip();
md.update(bbf);
bbf.clear();
bytesRead = fc.read(bbf);
}
fis.close();
byte[] mdBytes = md.digest();
StringBuilder hexString = new StringBuilder();
for (byte b : mdBytes) {
hexString.append(Integer.toHexString((LocalFileManager.BYTE_CAST_MASK & b)));
}
return hexString.toString();
}
}
}
public IMossFile getFile(String name) throws IOException;
public void registerFile(String name, String sha256, long size);
public void registerFile(String name, String sha256, long size) throws IOException;
public void receiveFileChunk(String sha512, int chunkId, ByteBuffer buf) throws IOException;
public void receiveFileChunk(String sha256, int chunkId, ByteBuffer buf) throws IOException;
public Class<? extends AssetLocator> getAssetLocatorClass();

View File

@ -19,4 +19,8 @@ public interface IMossFile {
public String getSha256();
public String getName();
public boolean isComplete();
public long getSize();
}

View File

@ -34,6 +34,17 @@ public class LocalFile implements IMossFile {
return name;
}
@Override
public boolean isComplete() {
// local files are always complete
return true;
}
@Override
public long getSize() {
return f.length();
}
private final String sha256;
public LocalFile(String name, File f) throws IOException, FileNotFoundException {
@ -47,7 +58,7 @@ public class LocalFile implements IMossFile {
this.numChunks = (int) Math.ceil(this.length
/ ((double) IMossFile.CHUNK_SIZE));
try {
this.sha256 = LocalFileManager.getHash(f);
this.sha256 = IFileManager.getHash(f);
logger.info(MessageFormat.format(Messages.getString("HASH_SUCCESS"), f.getAbsolutePath(), this.sha256));
} catch (NoSuchAlgorithmException e) {
logger.error(MessageFormat.format(Messages.getString("ALGO_NOT_FOUND"), f.getAbsolutePath()));

View File

@ -93,45 +93,6 @@ public class LocalFileManager implements IFileManager {
}
public static String getHash(File f) throws IOException,
NoSuchAlgorithmException, FileNotFoundException {
MessageDigest md = MessageDigest.getInstance("SHA-256"); //NON-NLS
try (FileInputStream fis = new FileInputStream(f)) {
try (FileChannel fc = fis.getChannel()) {
ByteBuffer bbf = ByteBuffer.allocateDirect(HASHING_BUFFER_SIZE);
int bytesRead;
bytesRead = fc.read(bbf);
while ((bytesRead != -1) && (bytesRead != 0)) {
bbf.flip();
md.update(bbf);
bbf.clear();
bytesRead = fc.read(bbf);
}
fis.close();
byte[] mdBytes = md.digest();
StringBuilder hexString = new StringBuilder();
for (byte b : mdBytes) {
hexString.append(Integer.toHexString((BYTE_CAST_MASK & b)));
}
return hexString.toString();
}
}
}
@Override
public List<? extends IMossFile> getFiles() {
return ImmutableList.copyOf(files.values());

View File

@ -4,40 +4,19 @@ package net.mosstest.servercore;
import java.util.Arrays;
/**
* The Class MossNetPacket.
*/
public class MossNetPacket {
/**
* The command id.
*/
int commandId;
public int commandId;
/**
* The payload.
*/
byte[] payload;
public byte[] payload;
/**
* The needs fast.
*/
boolean needsFast;
public boolean needsFast;
/**
* The needs ack.
*/
boolean needsAck;
public boolean needsAck;
/**
* The is important.
*/
boolean isImportant;
public boolean isImportant;
/**
* The sess.
*/
ServerSession sess;
public ServerSession sess;
/**
* Constructs a packet, for either sending or from receiving.

View File

@ -14,10 +14,13 @@ import org.jetbrains.annotations.NonNls;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class MossWorld {
static {
System.setSecurityManager(MosstestSecurityManager.instance);
Messages.changeLanguage(Locale.ITALIAN);
net.mosstest.scripting.Messages.changeLanguage(Locale.ITALIAN);
}
static Logger logger = Logger.getLogger(MossWorld.class);

View File

@ -1,23 +1,23 @@
package net.mosstest.servercore;
/**
* This exception is thrown in case of an unrecoverable error in Mosstest.
* At each level where a feature needs a clean shutdown, this exception must be caught, the shutdown performed, and the exception rethrown.
*/
public class MosstestFatalDeathException extends RuntimeException{
public MosstestFatalDeathException() {
super();
}
public MosstestFatalDeathException(String message) {
super(message);
}
public MosstestFatalDeathException(String message, Throwable cause) {
super(message, cause);
}
public MosstestFatalDeathException(Throwable cause) {
super(cause);
}
}
package net.mosstest.servercore;
/**
* This exception is thrown in case of an unrecoverable error in Mosstest.
* At each level where a feature needs a clean shutdown, this exception must be caught, the shutdown performed, and the exception rethrown.
*/
public class MosstestFatalDeathException extends RuntimeException{
public MosstestFatalDeathException() {
super();
}
public MosstestFatalDeathException(String message) {
super(message);
}
public MosstestFatalDeathException(String message, Throwable cause) {
super(message, cause);
}
public MosstestFatalDeathException(Throwable cause) {
super(cause);
}
}

View File

@ -7,19 +7,19 @@ import java.util.concurrent.ArrayBlockingQueue;
import java.util.logging.Level;
import com.jme3.material.RenderState;
import com.jme3.ui.Picture;
import jme3tools.optimize.GeometryBatchFactory;
import net.mosstest.scripting.MapChunk;
import net.mosstest.scripting.NodePosition;
import net.mosstest.scripting.Player;
import net.mosstest.scripting.Position;
import net.mosstest.servercore.FaceRenderer.Face;
import org.apache.log4j.Logger;
import com.jme3.app.SimpleApplication;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseAxisTrigger;
import com.jme3.light.DirectionalLight;
@ -28,8 +28,6 @@ import com.jme3.light.SpotLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue;
@ -43,107 +41,345 @@ import com.jme3.texture.Texture;
public class RenderProcessor extends SimpleApplication {
static Logger logger = Logger.getLogger(RenderProcessor.class);
private final float SPEED = 3f;
private final float BLOCK_SIZE = 20f;
private final float CHUNK_SIZE = 16 * BLOCK_SIZE;
private final float ROTATION_SPEED = 1f;
private final double BLOCK_OFFSET_FROM_CENTER = 8 * BLOCK_SIZE;
private final double CHUNK_OFFSET = 8 * BLOCK_SIZE;
private float[] locChanges = {0, 0, 0};
private double lastTime;
private boolean invertY = false;
private Vector3f initialUpVec;
private Object renderKey;
private Node worldNode;
private SpotLight spot;
private PointLight lamp;
private DirectionalLight sun;
//private HashMap<Position, RenderMapChunk> allChunks = new HashMap<Position, RenderMapChunk>();
public INodeManager nManager;
public IRenderPreparator rPreparator;
public Player player;
public ArrayBlockingQueue<MossRenderEvent> renderEventQueue = new ArrayBlockingQueue<>(
24000, false);
static Logger logger = Logger.getLogger(RenderProcessor.class);
private final float SPEED = 3f;
private final float NODE_SIZE = 20f;
private final float CHUNK_SIZE = 16*NODE_SIZE;
private final float ROTATION_SPEED = 1f;
private final double NODE_OFFSET_FROM_CENTER = 8 * NODE_SIZE;
private final double CHUNK_OFFSET = 8 * NODE_SIZE;
private float[] locChanges = { 0, 0, 0 };
private double lastTime;
private boolean invertY = false;
private Object renderKey;
private Node worldNode;
private SpotLight spot;
private PointLight lamp;
private DirectionalLight sun;
private ActivityListener activityListener;
private RotationListener rotationListener;
//private HashMap<Position, RenderMapChunk> allChunks = new HashMap<Position, RenderMapChunk>();
public INodeManager nManager;
public IRenderPreparator rPreparator;
public Player player;
public ArrayBlockingQueue<MossRenderEvent> renderEventQueue = new ArrayBlockingQueue<>(
24000, false);
public static RenderProcessor init(INodeManager manager, IRenderPreparator preparator) {
java.util.logging.Logger.getLogger("").setLevel(Level.WARNING);
RenderProcessor app = new RenderProcessor();
AppSettings settings = new AppSettings(true);
settings.setResolution(800, 600);
settings.setSamples(2);
settings.setFullscreen(false);
app.setSettings(settings);
app.setShowSettings(false);
app.initNodeManager(manager);
app.initPreparator(preparator);
app.initSecurityLock();
app.start();
return app;
}
public static RenderProcessor init(INodeManager manager, IRenderPreparator preparator) {
java.util.logging.Logger.getLogger("").setLevel(Level.WARNING);
RenderProcessor app = new RenderProcessor();
AppSettings settings = new AppSettings(true);
settings.setResolution(800, 600);
settings.setSamples(2);
settings.setFullscreen(false);
app.setSettings(settings);
app.setShowSettings(false);
app.initNodeManager(manager);
app.initPreparator(preparator);
app.initSecurityLock();
app.start();
return app;
}
private void initNodeManager (INodeManager manager) {
nManager = manager;
}
private void initNodeManager(INodeManager manager) {
nManager = manager;
}
private void initPreparator(IRenderPreparator prep) {
rPreparator = prep;
rPreparator.setRenderProcessor(this);
rPreparator.start();
}
private void initPreparator(IRenderPreparator prep) {
rPreparator = prep;
logger.info("The renderer is starting its preparator, which is of type " + prep.getClass().getSimpleName() + ".");
rPreparator.setRenderProcessor(this);
rPreparator.start();
}
private void initSecurityLock () {
renderKey = new Object();
}
private void initSecurityLock() {
renderKey = new Object();
}
@Override
public void simpleInitApp() {
lastTime = 0;
//acquireLock();
setupWorldNode ();
setupFlashlight();
setupSunlight();
setupLamplight();
setupPlayer();
assetManager.registerLocator("scripts", LocalAssetLocator.class);
setupHud();
flyCam.setEnabled(false);
setupListeners(cam.getUp().clone());
initKeyBindings();
preparatorChunkTest();
//blankChunkTest();
}
private void setupHud() {
Picture pic = new Picture("Crosshair");
pic.setImage(assetManager, "builtins/crosshair.png", true);
pic.setWidth(32);
pic.setHeight(32);
pic.setPosition(settings.getWidth()/2-16, settings.getHeight()/2-16);
guiNode.attachChild(pic);
@Override
public void simpleInitApp() {
lastTime = 0;
//acquireLock();
setupWorldNode();
setupFlashlight();
setupSunlight();
setupLamplight();
setupAssetManager();
setupPlayer();
preparatorChunkTest();
//blankChunkTest();
flyCam.setEnabled(false);
initialUpVec = cam.getUp().clone();
initKeyBindings();
}
@Override
public void simpleUpdate(float tpf) {
if (lastTime + 10 < System.currentTimeMillis()) {
move(locChanges[0], locChanges[1], locChanges[2]);
lastTime = System.currentTimeMillis();
}
inputManager.setCursorVisible(false);
MossRenderEvent myEvent = renderEventQueue.poll();
if (myEvent instanceof MossRenderStopEvent) {
logger.info("The renderer thread is shutting down.");
}
else if (myEvent instanceof MossRenderChunkEvent) {
renderChunk(((MossRenderChunkEvent) myEvent).getChk(),
((MossRenderChunkEvent) myEvent).getPos());
GeometryBatchFactory.optimize(worldNode);
}
}
//
public void renderChunk(MapChunk chk, Position pos) {
Mesh completeMesh = new Mesh ();
FaceRenderer.initialize();
//RenderNode[][][] renderNodes = new RenderNode[16][16][16];
for (byte i = 0; i < 16; i++) {
for (byte j = 0; j < 16; j++) {
for (byte k = 0; k < 16; k++) {
int[][][] nodes = chk.getNodes();
if (isNodeVisible(nodes, i, j, k)) {
int nVal = chk.getNodeId(i, j, k);
//MapNode node = nManager.getNode((short) nVal);
//Material mat = getMaterial((short) nVal);
if (nVal == 0) {}
else {
//z and y are switched on purpose.
float x = (float) ((pos.x + (CHUNK_SIZE * pos.x)) - NODE_OFFSET_FROM_CENTER + CHUNK_OFFSET + (i * NODE_SIZE));
float z = (float) ((pos.y - (CHUNK_SIZE * pos.y)) - NODE_OFFSET_FROM_CENTER + CHUNK_OFFSET + (j * NODE_SIZE));
float y = (float) ((pos.z + (CHUNK_SIZE * pos.z)) - NODE_OFFSET_FROM_CENTER + CHUNK_OFFSET + (k * NODE_SIZE));
for (Face face : Face.values()) {
if (FaceRenderer.isFaceVisible(face, nodes, i, j, k)) {
FaceRenderer.populateBuffers(face, x, y, z, NODE_SIZE);
}
}
//RenderNode geom = new RenderNode(mat, loc, NODE_SIZE, NodeManager.getNode((short)nVal)null);
//renderNodes[i][j][k] = geom;
}
}
}
}
}
FloatBuffer vertices = FaceRenderer.getVertices();
FloatBuffer tex = FaceRenderer.getTextureCoordinates();
FloatBuffer normals = FaceRenderer.getNormals();
IntBuffer indices = FaceRenderer.getIndices();
completeMesh.setBuffer(Type.Position, 3, vertices);
completeMesh.setBuffer(Type.Normal, 3, normals);
completeMesh.setBuffer(Type.Index, 3, indices);
completeMesh.setBuffer(Type.TexCoord, 2, tex);
completeMesh.updateBound();
Geometry geom = new Geometry("chunkMesh", completeMesh);
Material mat = getMaterial((short) 1);
geom.setMaterial(mat);
geom.setQueueBucket(RenderQueue.Bucket.Transparent);
worldNode.attachChild(geom);
//RenderMapChunk currentChunk = new RenderMapChunk(renderNodes);
//allChunks.put(pos, currentChunk);
}
private Material getMaterial(short nodeType) {
Material mat = null;
switch (nodeType) {
case 1:
mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
Texture tx = assetManager.loadTexture("default/grass.png");
//Texture tx = assetManager.loadTexture("default/item_torch.png");
tx.setMagFilter(Texture.MagFilter.Nearest);
mat.setTexture("DiffuseMap", tx);
mat.setBoolean("UseAlpha", true);
mat.getAdditionalRenderState().setAlphaTest(true);
mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
}
return mat;
}
public void getChunk (Position pos) {
MapChunk maybe = null;
try {maybe = rPreparator.requestChunk(pos);}
catch (MapGeneratorException e) {e.printStackTrace();}
catch (InterruptedException e) {e.printStackTrace();}
if (maybe != null) {renderChunk(maybe, pos);}
}
private void preparatorChunkTest() {
Position p1 = new Position(0, 0, 0, 0);
Position p2 = new Position(1, 0, 0, 0);
Position p3 = new Position(0, 1, 0, 0);
Position p4 = new Position(1, 1, 0, 0);
Position p5 = new Position(-1,0,0,0);
Position p6 = new Position(0,-1,0,0);
Position p7 = new Position(-1,-1,0,0);
@Override
public void simpleUpdate(float tpf) {
if (lastTime + 10 < System.currentTimeMillis()) {
move(locChanges[0], locChanges[1], locChanges[2]);
lastTime = System.currentTimeMillis();
}
inputManager.setCursorVisible(false);
MossRenderEvent myEvent = renderEventQueue.poll();
if (myEvent instanceof MossRenderStopEvent) {
logger.info("The renderer thread is shutting down.");
} else if (myEvent instanceof MossRenderChunkEvent) {
renderChunk(((MossRenderChunkEvent) myEvent).getChk(),
((MossRenderChunkEvent) myEvent).getPos());
GeometryBatchFactory.optimize(worldNode);
}
}
getChunk(p1);
getChunk(p2);
getChunk(p3);
getChunk(p4);
getChunk(p5);
getChunk(p6);
getChunk(p7);
}
private void blankChunkTest () {
Position p1 = new Position(0, 0, 0, 0);
Position p2 = new Position(1, 1, 1, 0);
int[][][] n1 = new int[16][16][16];
int[][][] n2 = new int[16][16][16];
for (int i = 0; i < n1.length; i++) {
for (int j = 0; j < n1[i].length; j++) {
for (int k = 0; k < n1[i][j].length; k++) {
n1[i][j][k] = 1;
n2[i][j][k] = 1;
}
}
}
MapChunk c1 = new MapChunk(p1, n1);
MapChunk c2 = new MapChunk(p2, n2);
MossRenderEvent e1 = new MossRenderChunkEvent(c1);
MossRenderEvent e2 = new MossRenderChunkEvent(c2);
renderEventQueue.add(e1);
renderEventQueue.add(e2);
//renderChunk(c2, p2);
}
public void getChunk(Position pos) {
MapChunk maybe = null;
try {
maybe = rPreparator.requestChunk(pos);
} catch (MapGeneratorException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (maybe != null) {
renderChunk(maybe, pos);
}
}
private void setupFlashlight () {
spot = new SpotLight();
spot.setSpotRange(300f);
spot.setSpotInnerAngle(15f * FastMath.DEG_TO_RAD);
spot.setSpotOuterAngle(35f * FastMath.DEG_TO_RAD);
spot.setColor(ColorRGBA.White.mult(3f));
spot.setPosition(cam.getLocation());
spot.setDirection(cam.getDirection());
rootNode.addLight(spot);
}
private void setupSunlight () {
sun = new DirectionalLight();
sun.setColor(ColorRGBA.White);
sun.setDirection(new Vector3f(-.5f, -.5f, -.5f).normalizeLocal());
rootNode.addLight(sun);
}
private void setupLamplight () {
lamp = new PointLight();
lamp.setColor(ColorRGBA.Yellow);
lamp.setRadius(4f);
lamp.setPosition(cam.getLocation());
rootNode.addLight(lamp);
}
private void setupWorldNode () {
worldNode = new Node("world");
rootNode.attachChild(worldNode);
}
private void setupPlayer () {
player = new Player ("Test Guy");
player.setPositionOffsets (0,5,0);
player.setChunkPosition(0,0,0);
cam.setLocation(new Vector3f(0, 0, 0));
}
private void move(float cx, float cy, float cz) {
Vector2f transVector = new Vector2f(cam.getDirection().x,
cam.getDirection().z).normalizeLocal();
worldNode.setLocalTranslation(worldNode
.getLocalTranslation()
.addLocal(
new Vector3f(-cz * transVector.x, 0f, -cz
* transVector.y))
.addLocal(-cx * transVector.y, 0f, cx * transVector.x)
.addLocal(0f, -cy, 0f));
double xpos = -(worldNode.getLocalTranslation().x);
double ypos = -(worldNode.getLocalTranslation().y);
double zpos = -(worldNode.getLocalTranslation().z);
int xchk = (int)Math.floor(xpos / (CHUNK_SIZE));
int ychk = (int)Math.floor(ypos / (CHUNK_SIZE));
int zchk = (int)Math.floor(zpos / (CHUNK_SIZE));
double xoffset = (xpos % CHUNK_SIZE)/NODE_SIZE;
double yoffset = (ypos % CHUNK_SIZE)/NODE_SIZE;
double zoffset = (zpos % CHUNK_SIZE)/NODE_SIZE;
synchronized(player.antiCheatDataLock){
player.setChunkPosition (xchk, ychk, zchk);
player.setPositionOffsets (xoffset, yoffset, zoffset);
}
}
private void setupListeners (Vector3f initialUpVec) {
rotationListener = new RotationListener (initialUpVec, invertY, cam, ROTATION_SPEED);
activityListener = new ActivityListener (locChanges, SPEED);
}
private boolean isNodeVisible (int[][][] chunk, int i, int j, int k) {
if (i == 0 || j == 0 || k == 0 || i == chunk.length-1 || j == chunk[0].length-1 || k == chunk[0][0].length-1) {
return true;
}
return (chunk[i+1][j][k] == 0 || chunk[i][j+1][k] == 0 || chunk[i][j][k+1] == 0 ||
chunk[i-1][j][k] == 0 || chunk[i][j-1][k] == 0 || chunk[i][j][k-1] == 0);
}
private void acquireLock () {
MosstestSecurityManager.instance.lock(renderKey, null);
}
private void releaseLock () {
MosstestSecurityManager.instance.unlock(renderKey);
}
private void initKeyBindings() {
inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_LSHIFT));
inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping("Forward", new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping("Back", new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping("TestFeature", new KeyTrigger(KeyInput.KEY_P));
inputManager.addMapping("CAM_Left", new MouseAxisTrigger(
MouseInput.AXIS_X, true), new KeyTrigger(KeyInput.KEY_LEFT));
inputManager.addMapping("CAM_Right", new MouseAxisTrigger(
MouseInput.AXIS_X, false), new KeyTrigger(KeyInput.KEY_RIGHT));
inputManager.addMapping("CAM_Up", new MouseAxisTrigger(
MouseInput.AXIS_Y, false), new KeyTrigger(KeyInput.KEY_UP));
inputManager.addMapping("CAM_Down", new MouseAxisTrigger(
MouseInput.AXIS_Y, true), new KeyTrigger(KeyInput.KEY_DOWN));
inputManager.addListener(activityListener, "Jump");
inputManager.addListener(activityListener, "Down");
inputManager.addListener(activityListener, "Left");
inputManager.addListener(activityListener, "Right");
inputManager.addListener(activityListener, "Forward");
inputManager.addListener(activityListener, "Back");
inputManager.addListener(rotationListener, "CAM_Left");
inputManager.addListener(rotationListener, "CAM_Right");
inputManager.addListener(rotationListener, "CAM_Up");
inputManager.addListener(rotationListener, "CAM_Down");
inputManager.addListener(activityListener, "TestFeature");
}
private static double intbound(double s, double ds) {
// Find the smallest positive t such that s+t*ds is an integer.
@ -284,406 +520,4 @@ public class RenderProcessor extends SimpleApplication {
System.out.println("x = [" + x + "], y = [" + y + "], z = [" + z + "], face = [" + face + "]");
return false;
}
public void renderChunk(MapChunk chk, Position pos) {
int vertexIndexCounter = 0;
Mesh completeMesh = new Mesh();
FloatBuffer vertices = getDirectFloatBuffer(950000);
FloatBuffer tex = getDirectFloatBuffer(950000);
FloatBuffer normals = getDirectFloatBuffer(950000);
IntBuffer indices = getDirectIntBuffer(950000);
//RenderNode[][][] renderNodes = new RenderNode[16][16][16];
for (byte i = 0; i < 16; i++) {
for (byte j = 0; j < 16; j++) {
for (byte k = 0; k < 16; k++) {
if (isNodeVisible(chk.getNodes(), i, j, k)) {
int nVal = chk.getNodeId(i, j, k);
//MapNode node = nManager.getNode((short) nVal);
//Material mat = getMaterial((short) nVal);
if (nVal == 0) {
} else {
//z and y are switched on purpose.
float x = (float) ((pos.x + (CHUNK_SIZE * pos.x)) - BLOCK_OFFSET_FROM_CENTER + CHUNK_OFFSET + (i * BLOCK_SIZE));
float z = (float) ((pos.y - (CHUNK_SIZE * pos.y)) - BLOCK_OFFSET_FROM_CENTER + CHUNK_OFFSET + (j * BLOCK_SIZE));
float y = (float) ((pos.z + (CHUNK_SIZE * pos.z)) - BLOCK_OFFSET_FROM_CENTER + CHUNK_OFFSET + (k * BLOCK_SIZE));
/**
* Vertices start at the top left corner and go clockwise around the face.
*/
vertices.put(x).put(y).put(z); //FRONT
vertices.put(x + BLOCK_SIZE).put(y).put(z);
vertices.put(x + BLOCK_SIZE).put(y).put(z - BLOCK_SIZE);
vertices.put(x).put(y).put(z - BLOCK_SIZE);
tex.put(0).put(0);
tex.put(0).put(1);
tex.put(1).put(1);
tex.put(1).put(0);
vertices.put(x).put(y + BLOCK_SIZE).put(z); //TOP
vertices.put(x + BLOCK_SIZE).put(y + BLOCK_SIZE).put(z);
vertices.put(x + BLOCK_SIZE).put(y).put(z);
vertices.put(x).put(y).put(z);
tex.put(0).put(0);
tex.put(0).put(1);
tex.put(1).put(1);
tex.put(1).put(0);
vertices.put(x + BLOCK_SIZE).put(y + BLOCK_SIZE).put(z);//BACK
vertices.put(x).put(y + BLOCK_SIZE).put(z);
vertices.put(x).put(y + BLOCK_SIZE).put(z - BLOCK_SIZE);
vertices.put(x + BLOCK_SIZE).put(y + BLOCK_SIZE).put(z - BLOCK_SIZE);
tex.put(0).put(0);
tex.put(0).put(1);
tex.put(1).put(1);
tex.put(1).put(0);
vertices.put(x + BLOCK_SIZE).put(y + BLOCK_SIZE).put(z - BLOCK_SIZE);
vertices.put(x).put(y + BLOCK_SIZE).put(z - BLOCK_SIZE);
vertices.put(x).put(y).put(z - BLOCK_SIZE);
vertices.put(x + BLOCK_SIZE).put(y).put(z - BLOCK_SIZE);
tex.put(0).put(0);
tex.put(0).put(1);
tex.put(1).put(1);
tex.put(1).put(0);
vertices.put(x).put(y + BLOCK_SIZE).put(z); //LEFT
vertices.put(x).put(y).put(z);
vertices.put(x).put(y).put(z - BLOCK_SIZE);
vertices.put(x).put(y + BLOCK_SIZE).put(z - BLOCK_SIZE);
tex.put(0).put(0);
tex.put(0).put(1);
tex.put(1).put(1);
tex.put(1).put(0);
vertices.put(x + BLOCK_SIZE).put(y).put(z); //RIGHT
vertices.put(x + BLOCK_SIZE).put(y + BLOCK_SIZE).put(z);
vertices.put(x + BLOCK_SIZE).put(y + BLOCK_SIZE).put(z - BLOCK_SIZE);
vertices.put(x + BLOCK_SIZE).put(y).put(z - BLOCK_SIZE);
tex.put(0).put(0);
tex.put(0).put(1);
tex.put(1).put(1);
tex.put(1).put(0);
for (int m = 0; m < 24; m++) {
normals.put(2).put(3).put(5);
}
indices.put(vertexIndexCounter + 0).put(vertexIndexCounter + 2).put(vertexIndexCounter + 1);//front
indices.put(vertexIndexCounter + 0).put(vertexIndexCounter + 3).put(vertexIndexCounter + 2);
indices.put(vertexIndexCounter + 4).put(vertexIndexCounter + 6).put(vertexIndexCounter + 5);//top
indices.put(vertexIndexCounter + 4).put(vertexIndexCounter + 7).put(vertexIndexCounter + 6);
indices.put(vertexIndexCounter + 8).put(vertexIndexCounter + 10).put(vertexIndexCounter + 9);//back
indices.put(vertexIndexCounter + 8).put(vertexIndexCounter + 11).put(vertexIndexCounter + 10);
indices.put(vertexIndexCounter + 12).put(vertexIndexCounter + 14).put(vertexIndexCounter + 13);//bottom
indices.put(vertexIndexCounter + 12).put(vertexIndexCounter + 15).put(vertexIndexCounter + 14);
indices.put(vertexIndexCounter + 16).put(vertexIndexCounter + 18).put(vertexIndexCounter + 17);//left
indices.put(vertexIndexCounter + 16).put(vertexIndexCounter + 19).put(vertexIndexCounter + 18);
indices.put(vertexIndexCounter + 20).put(vertexIndexCounter + 22).put(vertexIndexCounter + 21);//right
indices.put(vertexIndexCounter + 20).put(vertexIndexCounter + 23).put(vertexIndexCounter + 22);
//RenderNode geom = new RenderNode(mat, loc, BLOCK_SIZE, NodeManager.getNode((short)nVal)null);
//renderNodes[i][j][k] = geom;
vertexIndexCounter += 24;
}
}
}
}
}
Material mat = getMaterial((short) 1);
completeMesh.setBuffer(Type.Position, 3, vertices);
completeMesh.setBuffer(Type.Normal, 3, normals);
completeMesh.setBuffer(Type.Index, 3, indices);
completeMesh.setBuffer(Type.TexCoord, 2, tex);
completeMesh.updateBound();
Geometry geom = new Geometry("chunkMesh", completeMesh);
geom.setMaterial(mat);
geom.setQueueBucket(RenderQueue.Bucket.Transparent);
worldNode.attachChild(geom);
//RenderMapChunk currentChunk = new RenderMapChunk(renderNodes);
//allChunks.put(pos, currentChunk);
}
private Material getMaterial(short nodeType) {
Material mat = null;
switch (nodeType) {
case 1:
mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
Texture tx = assetManager.loadTexture("default/grass.png");
//Texture tx = assetManager.loadTexture("default/item_torch.png");
tx.setMagFilter(Texture.MagFilter.Nearest);
mat.setTexture("DiffuseMap", tx);
mat.setBoolean("UseAlpha", true);
mat.getAdditionalRenderState().setAlphaTest(true);
mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
}
return mat;
}
private void preparatorChunkTest() {
Position p1 = new Position(0, 0, 0, 0);
Position p2 = new Position(1, 0, 0, 0);
Position p3 = new Position(0, 1, 0, 0);
Position p4 = new Position(1, 1, 0, 0);
Position p5 = new Position(-1, 0, 0, 0);
Position p6 = new Position(0, -1, 0, 0);
Position p7 = new Position(-1, -1, 0, 0);
getChunk(p1);
getChunk(p2);
getChunk(p3);
getChunk(p4);
getChunk(p5);
getChunk(p6);
getChunk(p7);
}
private void blankChunkTest() {
Position p1 = new Position(0, 0, 0, 0);
Position p2 = new Position(1, 1, 1, 0);
int[][][] n1 = new int[16][16][16];
int[][][] n2 = new int[16][16][16];
for (int i = 0; i < n1.length; i++) {
for (int j = 0; j < n1[i].length; j++) {
for (int k = 0; k < n1[i][j].length; k++) {
n1[i][j][k] = 1;
n2[i][j][k] = 1;
}
}
}
MapChunk c1 = new MapChunk(p1, n1);
MapChunk c2 = new MapChunk(p2, n2);
MossRenderEvent e1 = new MossRenderChunkEvent(c1);
MossRenderEvent e2 = new MossRenderChunkEvent(c2);
renderEventQueue.add(e1);
renderEventQueue.add(e2);
//renderChunk(c2, p2);
}
private FloatBuffer getDirectFloatBuffer(int size) {
ByteBuffer temp = ByteBuffer.allocateDirect(size);
return temp.asFloatBuffer();
}
private IntBuffer getDirectIntBuffer(int size) {
ByteBuffer temp = ByteBuffer.allocateDirect(size);
return temp.asIntBuffer();
}
private void setupFlashlight() {
spot = new SpotLight();
spot.setSpotRange(300f);
spot.setSpotInnerAngle(15f * FastMath.DEG_TO_RAD);
spot.setSpotOuterAngle(35f * FastMath.DEG_TO_RAD);
spot.setColor(ColorRGBA.White.mult(3f));
spot.setPosition(cam.getLocation());
spot.setDirection(cam.getDirection());
rootNode.addLight(spot);
}
private void setupSunlight() {
sun = new DirectionalLight();
sun.setColor(ColorRGBA.White);
sun.setDirection(new Vector3f(-.5f, -.5f, -.5f).normalizeLocal());
rootNode.addLight(sun);
}
private void setupLamplight() {
lamp = new PointLight();
lamp.setColor(ColorRGBA.Yellow);
lamp.setRadius(4f);
lamp.setPosition(cam.getLocation());
rootNode.addLight(lamp);
}
private void setupWorldNode() {
worldNode = new Node("world");
rootNode.attachChild(worldNode);
}
private void setupPlayer() {
player = new Player("Test Guy");
player.setPositionOffsets(0, 5, 0);
player.setChunkPosition(0, 0, 0);
cam.setLocation(new Vector3f(0, 0, 0));
}
private void setupAssetManager() {
assetManager.registerLocator("scripts", LocalAssetLocator.class);
}
private void move(float cx, float cy, float cz) {
Vector2f transVector = new Vector2f(cam.getDirection().x,
cam.getDirection().z);
worldNode.setLocalTranslation(worldNode
.getLocalTranslation()
.addLocal(
new Vector3f(-cz * transVector.x, 0f, -cz
* transVector.y)
)
.addLocal(-cx * transVector.y, 0f, cx * transVector.x)
.addLocal(0f, -cy, 0f));
double xpos = -(worldNode.getLocalTranslation().x);
double ypos = -(worldNode.getLocalTranslation().y);
double zpos = -(worldNode.getLocalTranslation().z);
int xchk = (int) Math.floor(xpos / (CHUNK_SIZE));
int ychk = (int) Math.floor(ypos / (CHUNK_SIZE));
int zchk = (int) Math.floor(zpos / (CHUNK_SIZE));
double xoffset = (xpos % CHUNK_SIZE) / BLOCK_SIZE;
double yoffset = (ypos % CHUNK_SIZE) / BLOCK_SIZE;
double zoffset = (zpos % CHUNK_SIZE) / BLOCK_SIZE;
synchronized (player.antiCheatDataLock) {
player.setChunkPosition(xchk, ychk, zchk);
player.setPositionOffsets(xoffset, yoffset, zoffset);
}
}
private void rotateCamera(float value, Vector3f axis) {
Matrix3f mat = new Matrix3f();
mat.fromAngleNormalAxis(ROTATION_SPEED * value, axis);
Vector3f up = cam.getUp();
Vector3f left = cam.getLeft();
Vector3f dir = cam.getDirection();
mat.mult(up, up);
mat.mult(left, left);
mat.mult(dir, dir);
Quaternion q = new Quaternion();
q.fromAxes(left, up, dir);
q.normalizeLocal();
cam.setAxes(q);
spot.setDirection(cam.getDirection());
}
private boolean isNodeVisible(int[][][] chunk, int i, int j, int k) {
if (i == 0 || j == 0 || k == 0 || i == chunk.length - 1 || j == chunk[0].length - 1 || k == chunk[0][0].length - 1) {
return true;
}
return (chunk[i + 1][j][k] == 0 || chunk[i][j + 1][k] == 0 || chunk[i][j][k + 1] == 0 ||
chunk[i - 1][j][k] == 0 || chunk[i][j - 1][k] == 0 || chunk[i][j][k - 1] == 0);
}
private void acquireLock() {
MosstestSecurityManager.instance.lock(renderKey, null);
}
private void releaseLock() {
MosstestSecurityManager.instance.unlock(renderKey);
}
private void initKeyBindings() {
inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_LSHIFT));
inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping("Forward", new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping("Back", new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping("TestFeature", new KeyTrigger(KeyInput.KEY_P));
inputManager.addMapping("CAM_Left", new MouseAxisTrigger(
MouseInput.AXIS_X, true), new KeyTrigger(KeyInput.KEY_LEFT));
inputManager.addMapping("CAM_Right", new MouseAxisTrigger(
MouseInput.AXIS_X, false), new KeyTrigger(KeyInput.KEY_RIGHT));
inputManager.addMapping("CAM_Up", new MouseAxisTrigger(
MouseInput.AXIS_Y, false), new KeyTrigger(KeyInput.KEY_UP));
inputManager.addMapping("CAM_Down", new MouseAxisTrigger(
MouseInput.AXIS_Y, true), new KeyTrigger(KeyInput.KEY_DOWN));
inputManager.addListener(actionListener, "Jump");
inputManager.addListener(actionListener, "Down");
inputManager.addListener(actionListener, "Left");
inputManager.addListener(actionListener, "Right");
inputManager.addListener(actionListener, "Forward");
inputManager.addListener(actionListener, "Back");
inputManager.addListener(analogListener, "CAM_Left");
inputManager.addListener(analogListener, "CAM_Right");
inputManager.addListener(analogListener, "CAM_Up");
inputManager.addListener(analogListener, "CAM_Down");
inputManager.addListener(actionListener, "TestFeature");
}
private AnalogListener analogListener = new AnalogListener() {
public void onAnalog(String name, float value, float tpf) {
if (name.equals("CAM_Left")) {
rotateCamera(value, initialUpVec);
} else if (name.equals("CAM_Right")) {
rotateCamera(-value, initialUpVec);
} else if (name.equals("CAM_Up")) {
rotateCamera(-value * (invertY ? -1 : 1), cam.getLeft());
} else if (name.equals("CAM_Down")) {
rotateCamera(value * (invertY ? -1 : 1), cam.getLeft());
}
}
};
private ActionListener actionListener = new ActionListener() {
public void onAction(String name, boolean keyPressed, float tpf) {
if (name.equals("Jump") && keyPressed/* && jumpSPEED == 0 */) {
locChanges[1] = 2f;
} else if (name.equals("Jump") && !keyPressed) {
locChanges[1] = 0f;
}
if (name.equals("Down") && keyPressed) {
locChanges[1] = -2f;
} else if (name.equals("Down") && !keyPressed) {
locChanges[1] = 0f;
}
if (name.equals("Left") && keyPressed) {
locChanges[0] = SPEED;
} else if (name.equals("Left") && !keyPressed
&& locChanges[0] == SPEED) {
locChanges[0] = 0;
}
if (name.equals("Right") && keyPressed) {
locChanges[0] = -SPEED;
} else if (name.equals("Right") && !keyPressed
&& locChanges[0] == -SPEED) {
locChanges[0] = 0;
}
if (name.equals("Forward") && keyPressed) {
locChanges[2] = SPEED;
} else if (name.equals("Forward") && !keyPressed
&& locChanges[2] == SPEED) {
locChanges[2] = 0;
}
if (name.equals("Back") && keyPressed) {
locChanges[2] = -SPEED;
} else if (name.equals("Back") && !keyPressed
&& locChanges[2] == -SPEED) {
locChanges[2] = 0;
}
if (name.equals("TestFeature") && keyPressed) {
Position p = new Position(0, 2, 0, 0);
getChunk(p);
}
}
};
}
}

View File

@ -0,0 +1,54 @@
package net.mosstest.servercore;
import com.jme3.input.controls.AnalogListener;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
public class RotationListener implements AnalogListener {
private final float ROTATION_SPEED;
private Vector3f axis;
private boolean invertY;
private Camera cam;
public RotationListener (Vector3f v, boolean invert, Camera c, float rSpeed) {
axis = v;
System.out.println("AXIS: "+axis);
invertY = invert;
cam = c;
ROTATION_SPEED = rSpeed;
}
public void onAnalog(String name, float value, float tpf) {
if (name.equals("CAM_Left")) {
rotateCamera(value, axis);
} else if (name.equals("CAM_Right")) {
rotateCamera(-value, axis);
} else if (name.equals("CAM_Up")) {
rotateCamera(-value * (invertY ? -1 : 1), cam.getLeft());
} else if (name.equals("CAM_Down")) {
rotateCamera(value * (invertY ? -1 : 1), cam.getLeft());
}
}
private void rotateCamera(float value, Vector3f axis) {
Matrix3f mat = new Matrix3f();
mat.fromAngleNormalAxis(ROTATION_SPEED * value, axis);
Vector3f up = cam.getUp();
Vector3f left = cam.getLeft();
Vector3f dir = cam.getDirection();
mat.mult(up, up);
mat.mult(left, left);
mat.mult(dir, dir);
Quaternion q = new Quaternion();
q.fromAxes(left, up, dir);
q.normalizeLocal();
if (up.angleBetween(Vector3f.UNIT_Y) <= FastMath.HALF_PI) {
cam.setAxes(q);
}
}
}

View File

@ -0,0 +1,53 @@
AbstractNodeManager.DESC_UNKNOWN_NODE=Un pezzo sconosciuto del mondo
ClientNetworkingManager.DESC_NETWORK_TIMEOUT=La connessione al server \u00E8 stata persa o \u00E8 diventata troppo lenta per continuare. \nProbabilmente questo \u00E8 dovuto a una connessione instabile, WiFi debole, cavi allentati, o un problema di firewall.
ClientNetworkingManager.THREAD_NET_TIMEOUT=netTimeout
ClientNetworkingManager.THREAD_QUEUEING=netClientSendQueue
DefaultEventHandlers.NO_SUCH_CMD=Comando di chat inesistente.
EventProcessor.MSG_ADD_DYNAMIC=Thread aggiunto dinamicamente
EventProcessor.MSG_STOP_ONE_THREAD=Arresto di un thread...
EventProcessor.MSG_THREAD_START=E' iniziato un thread di lavoro.
EventProcessor.THREAD_NAME_MGR=EventProcessorManager
EventProcessor.THREADGROUP=EventProcessor
FuturesProcessor.FUTURES_THREAD=futuri
LocalRenderPreparator.MG_EXCEPT=Il generatore di mappe ha emesso una eccezione.
LocalRenderPreparator.MSG_REQUESTED=Aree richieste {0}, {1}, {2}.
LocalRenderPreparator.START_MSG=Il preparatore di rendering locale si sta avviando.
MapChunk.BAD_SER_VER=Versione di serializzazione sbagliata
MapDatabase.ERR_DB_FAIL=Caricamento della banca dati fallito.
MossDebugUtils.27=git.build.time
MossDebugUtils.MSG_BUILT_ON=Costruito su\:
MossDebugUtils.MSG_CORES=Processori disponibili\:
MossDebugUtils.MSG_EXCEPTION_CAUGHT=<<<Exception caught>>> \n
MossDebugUtils.MSG_FREE_SPACE=Spazio libero (byte)\:
MossDebugUtils.MSG_FREEMEM=Memoria libera (byte)\:
MossDebugUtils.MSG_FS_ROOT=File sistem radice\:
MossDebugUtils.MSG_IO_EXCEPTION=IOException in caricamento, forse inesistente?
MossDebugUtils.MSG_JAVA_PROPS=<<<Java properties>>>\n
MossDebugUtils.MSG_MAXMEM=Memoria massima (byte)\:
MossDebugUtils.MSG_MEM_NO_LIMIT=nessun limite
MossDebugUtils.MSG_SYS_PROPS=<<<System properties>>>\n
MossDebugUtils.MSG_TOTAL_MEM=Memoria totale (byte)\:
MossDebugUtils.MSG_TOTAL_SPACE=Spazio totale (byte)\:
MossDebugUtils.MSG_USABLE_SPACE=Spazio utilizzabile (byte)\:
MossGame.CFG_LOAD_ERR=Errore nel caricamento del file di configurazione.
MossGame.DIR_OR_CFG_NOT_FOUND=Cartella del gioco o file di configurazione non trovati.
MossGame.FILE_NOT_FOUND=Il file {0} non \u00E8 stato trovato.
MossScript.[NAME]_NOT_FOUND=\ non trovato\!
MossScript.MSG_IO_EXCEPTION=IOException con lo script chiamato
MossScript.MSG_OOPS=Abbiamo per le mani una situazione estremamente inaspettata
MossScript.MSG_SCRIPT_NAMED_[NAME]=Script chiamato
MossTest.PORT_DESC=Numero della porta da usare
MossTest.RUN_STANDALONE=Eseguire come server autonomo
MossWorld.ERR_DB=E' avvenuto un errore nell'apertura della banca dati. Probabilmente non \u00E8 accessibile, su un disco pieno, o corrotta.
MossWorld.MG_SELECT_FAILURE=Non \u00E8 stato possibile inserire il seme nel generatore di mappe.
MossWorld.NO_GAME_ID=Non \u00E8 specificato lo ID del gioco. Lo ID del gioco deve essere specificato in game.xml come <gameid>pincopallino</gameid> dove data/games/pincopallino \u00E8 una cartella con un gioco valido.
MossWorld.NO_NETWORKING_NOW=La connettivit\u00E0 non \u00E8 completa in questa versione.
NodeManager.DESC_UNKNWN_NODE=Un pezzo sconosciuto del mondo
ScriptEnv.ERR_SCRIPT_ERR=E'' avvenuto un errore di script. Eccezione impacchettata\: {0} \n
ServerNetworkingManager.ACCEPT_THREAD=svrNetAccept
ServerNetworkingManager.CONN_THREAD_NAME=thread di connessione
ServerNetworkingManager.THREADGROUP=SvrNetGroup
PACKET_INVALID_MAGIC=E'' stato ricevuto un pacchetto con un numero magico non valido ed \u00E8 stato gettato.
SERVER_CONN_TIMEOUT=La connessione al server \u00E8 scaduta o fallita in un altro modo.
FIXME_MESSAGE=Toccato un blocco di codice che rappresenta una funzionalit\u00E0 mancante. Per favore compilate un rapporto di bug oppure ricordatelo bruscamente agli sviluppatori in un altro modo.
EVENT_PROCESS_EXCEPTION=Notato {0} nell''elaborazione di un evento di tipo {1}. Il messaggio dell''eccezione era {2}.

View File

@ -1,5 +1,5 @@
package net.mosstest.servercore.serialization;
public interface IByteArrayConstructor<T> {
public T construct(byte[] buf);
}
package net.mosstest.servercore.serialization;
public interface IByteArrayConstructor<T> {
public T construct(byte[] buf);
}

View File

@ -1,5 +1,7 @@
package net.mosstest.servercore.serialization;
public interface IByteArrayWritable {
public byte[] toBytes();
}

View File

@ -1,5 +1,5 @@
package net.mosstest.servercore.serialization;
public interface IManaged<T> {
public void setManager(T t);
}
package net.mosstest.servercore.serialization;
public interface IManaged<T> {
public void setManager(T t);
}

View File

@ -1,62 +1,62 @@
package net.mosstest.tests;
import net.mosstest.scripting.MapNode;
import net.mosstest.servercore.MosstestSecurityManager;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import static org.junit.Assert.*;
public class SecurityManagerTest {
static MosstestSecurityManager m;
@BeforeClass
public static void setUp() throws IOException {
m = new MosstestSecurityManager(true);
m.setTrustedBasedir(new File(""));
System.setSecurityManager(m);
}
@Test
public void testAccessUnlocked() {
m.setThreadContext(MosstestSecurityManager.ThreadContext.CONTEXT_ENGINE);
m.checkAccept("192.168.1.1", 13);
m.checkRead("C:\\zoom.png");
m.checkRead("/c/zoom.png");
testLocked();
}
public void testLocked() {
Object o = new Object();
m.lock(o, MosstestSecurityManager.ThreadContext.CONTEXT_SCRIPT);
try {
m.checkAccept("192.168.1.1", 13);
fail("CheckAccept passed wrongly!");
} catch (SecurityException e) {
}
try {
m.checkRead("C:\\lock.png");
fail("Allowed an illegal Windows path");
} catch (SecurityException e) {
}
try {
m.checkRead("/c/linuxlock.png");
System.out.println("LINUXLOCK");
fail("Allowed an illegal unix path");
} catch (SecurityException e) {
}
try {
MapNode n = new MapNode("test", "test", "test", 0);
} catch (SecurityException e) {
fail("disallowed a classload");
}
m.unlock(o);
}
}
package net.mosstest.tests;
import net.mosstest.scripting.MapNode;
import net.mosstest.servercore.MosstestSecurityManager;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import static org.junit.Assert.*;
public class SecurityManagerTest {
static MosstestSecurityManager m;
@BeforeClass
public static void setUp() throws IOException {
m = new MosstestSecurityManager(true);
m.setTrustedBasedir(new File(""));
System.setSecurityManager(m);
}
@Test
public void testAccessUnlocked() {
m.setThreadContext(MosstestSecurityManager.ThreadContext.CONTEXT_ENGINE);
m.checkAccept("192.168.1.1", 13);
m.checkRead("C:\\zoom.png");
m.checkRead("/c/zoom.png");
testLocked();
}
public void testLocked() {
Object o = new Object();
m.lock(o, MosstestSecurityManager.ThreadContext.CONTEXT_SCRIPT);
try {
m.checkAccept("192.168.1.1", 13);
fail("CheckAccept passed wrongly!");
} catch (SecurityException e) {
}
try {
m.checkRead("C:\\lock.png");
fail("Allowed an illegal Windows path");
} catch (SecurityException e) {
}
try {
m.checkRead("/c/linuxlock.png");
System.out.println("LINUXLOCK");
fail("Allowed an illegal unix path");
} catch (SecurityException e) {
}
try {
MapNode n = new MapNode("test", "test", "test", 0);
} catch (SecurityException e) {
fail("disallowed a classload");
}
m.unlock(o);
}
}

View File

@ -1,97 +1,97 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<config xmlns="http://zanata.org/namespace/config/">
<url>https://translate.zanata.org/zanata/</url>
<project>mosstest</project>
<project-version>initial</project-version>
<project-type>properties</project-type>
<locales>
<locale>ar</locale>
<locale>as</locale>
<locale>bg</locale>
<locale>bn-IN</locale>
<locale>ca</locale>
<locale>cs</locale>
<locale>da</locale>
<locale>de-CH</locale>
<locale>de-DE</locale>
<locale>el</locale>
<locale>en-GB</locale>
<locale>es-ES</locale>
<locale>es-MX</locale>
<locale>fa</locale>
<locale>fi</locale>
<locale>fr</locale>
<locale>gu</locale>
<locale>he</locale>
<locale>hi</locale>
<locale>hr</locale>
<locale>hu</locale>
<locale>id</locale>
<locale>is</locale>
<locale>it</locale>
<locale>ja</locale>
<locale>kn</locale>
<locale>ko</locale>
<locale>lv</locale>
<locale>ml</locale>
<locale>mr</locale>
<locale>ms</locale>
<locale>nb</locale>
<locale>nl</locale>
<locale>or</locale>
<locale>pl</locale>
<locale>pt-PT</locale>
<locale>pt-BR</locale>
<locale>ru</locale>
<locale>si</locale>
<locale>sk</locale>
<locale>sr-Cyrl</locale>
<locale>sr-Latn</locale>
<locale>sv</locale>
<locale>ta-IN</locale>
<locale>te</locale>
<locale>th</locale>
<locale>tr</locale>
<locale>uk</locale>
<locale>zh-Hans-CN</locale>
<locale>zh-Hant-TW</locale>
<locale>af</locale>
<locale>am</locale>
<locale>az</locale>
<locale>bn-BD</locale>
<locale>cy</locale>
<locale>eo</locale>
<locale>et</locale>
<locale>eu</locale>
<locale>ga</locale>
<locale>gl</locale>
<locale>ka</locale>
<locale>lt</locale>
<locale>nn</locale>
<locale>ro</locale>
<locale>sl</locale>
<locale>sq</locale>
<locale>vi</locale>
<locale>ast</locale>
<locale>bs</locale>
<locale>nds</locale>
<locale>ky</locale>
<locale>la</locale>
<locale>mn</locale>
<locale>tl</locale>
<locale>xh</locale>
<locale>pa</locale>
<locale>mai</locale>
<locale>es</locale>
<locale>de</locale>
<locale>brx</locale>
<locale>ta</locale>
<locale>zh-CN</locale>
<locale>zh-TW</locale>
<locale>br</locale>
<locale>kk</locale>
<locale>anp</locale>
</locales>
</config>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<config xmlns="http://zanata.org/namespace/config/">
<url>https://translate.zanata.org/zanata/</url>
<project>mosstest</project>
<project-version>initial</project-version>
<project-type>properties</project-type>
<locales>
<locale>ar</locale>
<locale>as</locale>
<locale>bg</locale>
<locale>bn-IN</locale>
<locale>ca</locale>
<locale>cs</locale>
<locale>da</locale>
<locale>de-CH</locale>
<locale>de-DE</locale>
<locale>el</locale>
<locale>en-GB</locale>
<locale>es-ES</locale>
<locale>es-MX</locale>
<locale>fa</locale>
<locale>fi</locale>
<locale>fr</locale>
<locale>gu</locale>
<locale>he</locale>
<locale>hi</locale>
<locale>hr</locale>
<locale>hu</locale>
<locale>id</locale>
<locale>is</locale>
<locale>it</locale>
<locale>ja</locale>
<locale>kn</locale>
<locale>ko</locale>
<locale>lv</locale>
<locale>ml</locale>
<locale>mr</locale>
<locale>ms</locale>
<locale>nb</locale>
<locale>nl</locale>
<locale>or</locale>
<locale>pl</locale>
<locale>pt-PT</locale>
<locale>pt-BR</locale>
<locale>ru</locale>
<locale>si</locale>
<locale>sk</locale>
<locale>sr-Cyrl</locale>
<locale>sr-Latn</locale>
<locale>sv</locale>
<locale>ta-IN</locale>
<locale>te</locale>
<locale>th</locale>
<locale>tr</locale>
<locale>uk</locale>
<locale>zh-Hans-CN</locale>
<locale>zh-Hant-TW</locale>
<locale>af</locale>
<locale>am</locale>
<locale>az</locale>
<locale>bn-BD</locale>
<locale>cy</locale>
<locale>eo</locale>
<locale>et</locale>
<locale>eu</locale>
<locale>ga</locale>
<locale>gl</locale>
<locale>ka</locale>
<locale>lt</locale>
<locale>nn</locale>
<locale>ro</locale>
<locale>sl</locale>
<locale>sq</locale>
<locale>vi</locale>
<locale>ast</locale>
<locale>bs</locale>
<locale>nds</locale>
<locale>ky</locale>
<locale>la</locale>
<locale>mn</locale>
<locale>tl</locale>
<locale>xh</locale>
<locale>pa</locale>
<locale>mai</locale>
<locale>es</locale>
<locale>de</locale>
<locale>brx</locale>
<locale>ta</locale>
<locale>zh-CN</locale>
<locale>zh-TW</locale>
<locale>br</locale>
<locale>kk</locale>
<locale>anp</locale>
</locales>
</config>