Merge remote-tracking branch 'origin' into 021214renderer
Conflicts: src/net/mosstest/servercore/RenderProcessor.javamaster
commit
57c2fe19d7
|
@ -0,0 +1,144 @@
|
|||
<?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>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<root>
|
||||
<item name='java.util.HashMap V put(K, V) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NonNls'/>
|
||||
</item>
|
||||
</root>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/target/classes" />
|
||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
|
@ -10,7 +10,6 @@
|
|||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Maven: com.google.guava:guava:15.0" 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 +43,7 @@
|
|||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.8.1" level="project" />
|
||||
<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" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
|
11
pom.xml
11
pom.xml
|
@ -36,8 +36,8 @@
|
|||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
@ -115,7 +115,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<version>2.1</version>
|
||||
|
||||
<executions>
|
||||
|
||||
|
@ -331,6 +331,11 @@
|
|||
<artifactId>commons-io</artifactId>
|
||||
<version>2.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.intellij</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>9.0.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.mosstest.launcher;
|
||||
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
|
@ -58,7 +60,7 @@ public class GUIBugReportDialog extends JDialog {
|
|||
*
|
||||
* @param traceback the traceback
|
||||
*/
|
||||
public GUIBugReportDialog(String traceback) {
|
||||
public GUIBugReportDialog(@NonNls String traceback) {
|
||||
setModal(true);
|
||||
setModalityType(ModalityType.APPLICATION_MODAL);
|
||||
setMinimumSize(new Dimension(640, 480));
|
||||
|
@ -69,7 +71,7 @@ public class GUIBugReportDialog extends JDialog {
|
|||
contentPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
this.contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
getContentPane().add(this.contentPanel, BorderLayout.CENTER);
|
||||
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
|
||||
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.PAGE_AXIS));
|
||||
{
|
||||
JPanel namePanel = new JPanel();
|
||||
namePanel.setMaximumSize(new Dimension(32767, 20));
|
||||
|
@ -78,7 +80,7 @@ public class GUIBugReportDialog extends JDialog {
|
|||
|
||||
{
|
||||
lblName = new JLabel(Messages.getString("GUIBugReportDialog.DLG_BUG_NAME")); //$NON-NLS-1$
|
||||
namePanel.add(lblName, BorderLayout.WEST);
|
||||
namePanel.add(lblName, BorderLayout.LINE_START);
|
||||
lblName.setHorizontalTextPosition(SwingConstants.LEFT);
|
||||
lblName.setHorizontalAlignment(SwingConstants.LEFT);
|
||||
lblName.setAlignmentY(Component.TOP_ALIGNMENT);
|
||||
|
@ -99,7 +101,7 @@ public class GUIBugReportDialog extends JDialog {
|
|||
emailPanel.setLayout(new BorderLayout(0, 0));
|
||||
{
|
||||
JLabel lblEmailoptional = new JLabel(Messages.getString("GUIBugReportDialog.DLG_BUG_EMAIL")); //$NON-NLS-1$
|
||||
emailPanel.add(lblEmailoptional, BorderLayout.WEST);
|
||||
emailPanel.add(lblEmailoptional, BorderLayout.LINE_START);
|
||||
}
|
||||
{
|
||||
this.email = new JTextField();
|
||||
|
@ -115,7 +117,7 @@ public class GUIBugReportDialog extends JDialog {
|
|||
summaryPnl.setLayout(new BorderLayout(0, 0));
|
||||
{
|
||||
JLabel lblProblemDescription = new JLabel(Messages.getString("GUIBugReportDialog.DLG_BUG_SUMMARY")); //$NON-NLS-1$
|
||||
summaryPnl.add(lblProblemDescription, BorderLayout.WEST);
|
||||
summaryPnl.add(lblProblemDescription, BorderLayout.LINE_START);
|
||||
}
|
||||
{
|
||||
this.problemSummary = new JTextField();
|
||||
|
@ -132,7 +134,7 @@ public class GUIBugReportDialog extends JDialog {
|
|||
JLabel lblDetailedProblemDescription = new JLabel(
|
||||
Messages.getString("GUIBugReportDialog.DLG_BUG_DESC")); //$NON-NLS-1$
|
||||
lblDetailedProblemDescription.setVerticalAlignment(SwingConstants.TOP);
|
||||
descPanel.add(lblDetailedProblemDescription, BorderLayout.WEST);
|
||||
descPanel.add(lblDetailedProblemDescription, BorderLayout.LINE_START);
|
||||
}
|
||||
{
|
||||
JScrollPane scrollPane = new JScrollPane();
|
||||
|
@ -154,7 +156,7 @@ public class GUIBugReportDialog extends JDialog {
|
|||
{
|
||||
chckbxIncludeTechnicalInformation = new JCheckBox(
|
||||
Messages.getString("GUIBugReportDialog.DLG_CHECKBOX_INCLUDE_TECH_INFO")); //$NON-NLS-1$
|
||||
techInfoPanel.add(chckbxIncludeTechnicalInformation, BorderLayout.WEST);
|
||||
techInfoPanel.add(chckbxIncludeTechnicalInformation, BorderLayout.LINE_START);
|
||||
chckbxIncludeTechnicalInformation.setLocation(new Point(2, 0));
|
||||
chckbxIncludeTechnicalInformation.setVerticalAlignment(SwingConstants.TOP);
|
||||
chckbxIncludeTechnicalInformation.setHorizontalTextPosition(SwingConstants.LEFT);
|
||||
|
@ -178,8 +180,8 @@ public class GUIBugReportDialog extends JDialog {
|
|||
}
|
||||
{
|
||||
JPanel buttonPane = new JPanel();
|
||||
getContentPane().add(buttonPane, BorderLayout.SOUTH);
|
||||
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
|
||||
getContentPane().add(buttonPane, BorderLayout.PAGE_END);
|
||||
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
|
||||
{
|
||||
JProgressBar progressBar = new JProgressBar();
|
||||
buttonPane.add(progressBar);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package net.mosstest.launcher;
|
||||
|
||||
import net.mosstest.servercore.*;
|
||||
import org.apache.commons.configuration.ConfigurationException;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
@ -12,6 +12,7 @@ import java.awt.event.ActionEvent;
|
|||
import java.awt.event.ActionListener;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
|
@ -89,7 +90,7 @@ public class GUIClientsideLauncher {
|
|||
* @throws InterruptedException the interrupted exception
|
||||
*/
|
||||
public static void main(String[] args) throws InvocationTargetException, InterruptedException {
|
||||
logger.info("Mosstest client starting...");
|
||||
logger.info(Messages.getString("MOSS_CLIENT_STARTING"));
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException
|
||||
|
@ -125,6 +126,7 @@ public class GUIClientsideLauncher {
|
|||
*
|
||||
* @param singleplayerEntries the singleplayer entries
|
||||
*/
|
||||
@SuppressWarnings("StringConcatenation")
|
||||
private void initialize(ArrayList<SingleplayerListEntry> singleplayerEntries) {
|
||||
this.frmMosstestClientLauncher = new JDialog();
|
||||
this.frmMosstestClientLauncher.setModal(true);
|
||||
|
@ -153,7 +155,7 @@ public class GUIClientsideLauncher {
|
|||
this.table.getColumnModel().getColumn(2).setPreferredWidth(104);
|
||||
this.table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
JPanel singleplayerControlBtns = new JPanel();
|
||||
singleplayerTab.add(singleplayerControlBtns, BorderLayout.SOUTH);
|
||||
singleplayerTab.add(singleplayerControlBtns, BorderLayout.PAGE_END);
|
||||
singleplayerControlBtns.setLayout(new GridLayout(0, 4, 0, 0));
|
||||
|
||||
JButton btnPlaySingleplayer = new JButton(
|
||||
|
@ -164,7 +166,7 @@ public class GUIClientsideLauncher {
|
|||
int row = GUIClientsideLauncher.this.table.getSelectedRow();
|
||||
if (row < 0) {
|
||||
|
||||
logger.warn("An attempt was made to start gameplay without selecting a world.");
|
||||
logger.warn(Messages.getString("GAMEPLAY_NO_WORLD"));
|
||||
JOptionPane.showMessageDialog(
|
||||
null,
|
||||
Messages.getString("GUIClientsideLauncher.ERR_NO_WORLD_SELECTED"), //$NON-NLS-1$
|
||||
|
@ -181,11 +183,11 @@ public class GUIClientsideLauncher {
|
|||
try {
|
||||
|
||||
MossWorld w = new MossWorld((String) GUIClientsideLauncher.this.table.getModel().getValueAt(row, 0), -16511);
|
||||
} catch (MossWorldLoadException | MapDatabaseException | IOException | ConfigurationException e) {
|
||||
logger.error("Uncaught exception in game code, opening bug reporter.");
|
||||
} catch (MossWorldLoadException | MapDatabaseException | IOException e) {
|
||||
logger.error(Messages.getString("GAME_UNCAUGHT_EXCEPT"));
|
||||
|
||||
String fname = MossDebugUtils.writeStracktrace(e);
|
||||
logger.error("Stracktrace has been written to " + fname);
|
||||
logger.error(MessageFormat.format(Messages.getString("STACKTRACE_WRITTEN"), fname));
|
||||
GUIBugReportDialog bg = new GUIBugReportDialog(
|
||||
MossDebugUtils.getDebugInformation(e));
|
||||
bg.setVisible(true);
|
||||
|
@ -203,16 +205,10 @@ public class GUIClientsideLauncher {
|
|||
GUIWorldCreationDialog dlg = new GUIWorldCreationDialog();
|
||||
dlg.setVisible(true);
|
||||
if (dlg.dlgResult) {
|
||||
logger.debug("Got world: "
|
||||
+ dlg.nameField.getText()
|
||||
+ " with desc: "
|
||||
+ dlg.inputDesc.getText()
|
||||
+ " with game: "
|
||||
+ dlg.comboBox.getItemAt(dlg.comboBox
|
||||
.getSelectedIndex())); //$NON-NLS-1$
|
||||
// TODO actually create world
|
||||
|
||||
} else
|
||||
logger.info("World creation cancelled");
|
||||
logger.info(Messages.getString("WORLD_CREATION_CXLD"));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -229,7 +225,7 @@ public class GUIClientsideLauncher {
|
|||
int row = GUIClientsideLauncher.this.table.getSelectedRow();
|
||||
if (row < 0) {
|
||||
|
||||
logger.warn("An attempt was made to delete a world, but none was selected.");
|
||||
logger.warn(Messages.getString("NO_WORLD_TO_DELETE"));
|
||||
JOptionPane.showMessageDialog(
|
||||
null,
|
||||
Messages.getString("GUIClientsideLauncher.DLG_NO_WORLD_TO_DELETE"), //$NON-NLS-1$
|
||||
|
@ -290,7 +286,7 @@ public class GUIClientsideLauncher {
|
|||
btnVisitForums.setEnabled(false);
|
||||
communityToolsButtonPanel.add(btnVisitForums);
|
||||
|
||||
JTextArea textArea = new JTextArea();
|
||||
@NonNls JTextArea textArea = new JTextArea();
|
||||
aboutTab.add(textArea);
|
||||
textArea.setText(" __ __ ____ _____ _____ _______ ______ _____ _______ \r\n"
|
||||
+ " | \\/ |/ __ \\ / ____/ ____|__ __| ____|/ ____|__ __|\r\n"
|
||||
|
|
|
@ -80,7 +80,7 @@ public class GUIWorldCreationDialog extends JDialog {
|
|||
|
||||
{
|
||||
JLabel lblWorldName = new JLabel(Messages.getString("GUIWorldCreationDialog.WORLD_NAME")); //$NON-NLS-1$
|
||||
namePanel.add(lblWorldName, BorderLayout.WEST);
|
||||
namePanel.add(lblWorldName, BorderLayout.LINE_START);
|
||||
}
|
||||
{
|
||||
this.nameField = new JTextField();
|
||||
|
@ -97,7 +97,7 @@ public class GUIWorldCreationDialog extends JDialog {
|
|||
descPnl.setLayout(new BorderLayout(0, 0));
|
||||
{
|
||||
JLabel lblDescription = new JLabel(Messages.getString("GUIWorldCreationDialog.WORLD_DESC")); //$NON-NLS-1$
|
||||
descPnl.add(lblDescription, BorderLayout.WEST);
|
||||
descPnl.add(lblDescription, BorderLayout.LINE_START);
|
||||
}
|
||||
{
|
||||
this.inputDesc = new JTextField();
|
||||
|
@ -113,7 +113,7 @@ public class GUIWorldCreationDialog extends JDialog {
|
|||
profPnl.setLayout(new BorderLayout(0, 0));
|
||||
{
|
||||
JLabel lblGameProfile = new JLabel(Messages.getString("GUIWorldCreationDialog.GAME_PROFILE")); //$NON-NLS-1$
|
||||
profPnl.add(lblGameProfile, BorderLayout.WEST);
|
||||
profPnl.add(lblGameProfile, BorderLayout.LINE_START);
|
||||
}
|
||||
{
|
||||
this.comboBox = new JComboBox<String>();
|
||||
|
@ -124,8 +124,8 @@ public class GUIWorldCreationDialog extends JDialog {
|
|||
{
|
||||
JPanel buttonPane = new JPanel();
|
||||
buttonPane.setMaximumSize(new Dimension(32767, 23));
|
||||
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
|
||||
getContentPane().add(buttonPane, BorderLayout.SOUTH);
|
||||
buttonPane.setLayout(new FlowLayout(FlowLayout.TRAILING));
|
||||
getContentPane().add(buttonPane, BorderLayout.PAGE_END);
|
||||
{
|
||||
JButton okButton = new JButton(Messages.getString("GUIWorldCreationDialog.OK")); //$NON-NLS-1$
|
||||
okButton.addActionListener(new ActionListener() {
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.awt.BorderLayout;
|
|||
import java.awt.FlowLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
|
@ -54,14 +55,14 @@ public class GUIWorldDeletionDialog extends JDialog {
|
|||
getContentPane().setLayout(new BorderLayout());
|
||||
this.contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
getContentPane().add(this.contentPanel, BorderLayout.CENTER);
|
||||
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.X_AXIS));
|
||||
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.LINE_AXIS));
|
||||
{
|
||||
JPanel panel = new JPanel();
|
||||
contentPanel.add(panel);
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
|
||||
|
||||
{
|
||||
JLabel lblAreYouSure = new JLabel(Messages.getString("GUIWorldDeletionDialog.AREYOUSURE_TEXT")+worldName+Messages.getString("GUIWorldDeletionDialog.QUESTIONMARK_CANNOT_UNDO")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
JLabel lblAreYouSure = new JLabel(MessageFormat.format(Messages.getString("GUIWorldDeletionDialog.AREYOUSURE_TEXT"),worldName));
|
||||
panel.add(lblAreYouSure);
|
||||
lblAreYouSure.setHorizontalTextPosition(SwingConstants.LEFT);
|
||||
lblAreYouSure.setHorizontalAlignment(SwingConstants.LEFT);
|
||||
|
@ -69,8 +70,8 @@ public class GUIWorldDeletionDialog extends JDialog {
|
|||
}
|
||||
{
|
||||
JPanel buttonPane = new JPanel();
|
||||
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
|
||||
getContentPane().add(buttonPane, BorderLayout.SOUTH);
|
||||
buttonPane.setLayout(new FlowLayout(FlowLayout.TRAILING));
|
||||
getContentPane().add(buttonPane, BorderLayout.PAGE_END);
|
||||
{
|
||||
JButton btnYes = new JButton(Messages.getString("GUIWorldDeletionDialog.YES")); //$NON-NLS-1$
|
||||
btnYes.addActionListener(new ActionListener() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package net.mosstest.launcher;
|
||||
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
|
@ -22,9 +23,9 @@ public class Messages {
|
|||
*
|
||||
* @param identifier the identifier
|
||||
*/
|
||||
public static void changeLanguage(String identifier) {
|
||||
resBundle = ResourceBundle.getBundle(BUNDLE_NAME + "." + identifier);
|
||||
}
|
||||
public static void changeLanguage(Locale identifier) {
|
||||
resBundle = ResourceBundle.getBundle(BUNDLE_NAME, identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new messages.
|
||||
|
|
|
@ -39,8 +39,13 @@ GUIWorldCreationDialog.GAME_PROFILE=Game profile:
|
|||
GUIWorldCreationDialog.OK=OK
|
||||
GUIWorldCreationDialog.WORLD_DESC=Description:
|
||||
GUIWorldCreationDialog.WORLD_NAME=World name:
|
||||
GUIWorldDeletionDialog.AREYOUSURE_TEXT=Are you sure you wish to delete the world called
|
||||
GUIWorldDeletionDialog.AREYOUSURE_TEXT=Are you sure you wish to delete {0}? This cannot be undone.
|
||||
GUIWorldDeletionDialog.DLG_TITLE=Delete singleplayer world...
|
||||
GUIWorldDeletionDialog.NO=No
|
||||
GUIWorldDeletionDialog.QUESTIONMARK_CANNOT_UNDO=? This operation cannot be undone.
|
||||
GUIWorldDeletionDialog.YES=Yes
|
||||
GAMEPLAY_NO_WORLD=An attempt was made to start gameplay without selecting a world.
|
||||
GAME_UNCAUGHT_EXCEPT=Uncaught exception in game code, opening bug reporter.
|
||||
STACKTRACE_WRITTEN=Stracktrace has been written to {0}
|
||||
WORLD_CREATION_CXLD=World creation cancelled
|
||||
NO_WORLD_TO_DELETE=An attempt was made to delete a world, but none was selected.
|
||||
|
|
|
@ -20,7 +20,7 @@ public class ABMManager {
|
|||
}
|
||||
|
||||
// It's acceptable to have multiple fp's running.
|
||||
private final FuturesProcessor fp = new FuturesProcessor(EngineSettings.getInt("abmThreads", 2));
|
||||
private final FuturesProcessor fp = new FuturesProcessor(EngineSettings.getInt("abmThreads", 2)); //NON-NLS
|
||||
|
||||
// no references kept to map, only to the set
|
||||
private final Set<MapChunk> loadedChunks = Collections.newSetFromMap(new ConcurrentHashMap<MapChunk, Boolean>());
|
||||
|
|
|
@ -1,20 +1,10 @@
|
|||
package net.mosstest.scripting;
|
||||
|
||||
import net.mosstest.servercore.AbstractByteArrayStorable;
|
||||
import net.mosstest.servercore.serialization.IByteArrayWriteable;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class AbstractMapChunk extends AbstractByteArrayStorable<Void> {
|
||||
public abstract class AbstractMapChunk implements IByteArrayWriteable {
|
||||
int CHUNK_DIMENSION = 16;
|
||||
|
||||
public AbstractMapChunk(byte[] buf) throws IOException{
|
||||
super(buf);
|
||||
}
|
||||
|
||||
protected AbstractMapChunk() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract boolean equals(Object o);
|
||||
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
package net.mosstest.scripting;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class CubeTextureSet {
|
||||
// 0 = top
|
||||
// 1 = front(toward player when placing, relative to facedir)
|
||||
// 2 = right(relative to facedir)
|
||||
// 3 = back (away from player when placing, relative to facedir)
|
||||
// 4 = left (relative to facedir)
|
||||
// 5 = bottom
|
||||
private String[] textures = new String[6];
|
||||
|
||||
public CubeTextureSet(String top, String front, String right, String back, String left, String bottom) {
|
||||
this.textures = new String[]{top, front, right, back, left, bottom};
|
||||
}
|
||||
|
||||
public CubeTextureSet(){
|
||||
textures = new String[6];
|
||||
}
|
||||
|
||||
public void setAll(String tex){
|
||||
for(int i = 0; i < 6; i++){
|
||||
textures[i] = tex;
|
||||
}
|
||||
}
|
||||
|
||||
public void setTopBottom(String tex){
|
||||
textures[0] = tex;
|
||||
textures[5] = tex;
|
||||
}
|
||||
|
||||
public void setCircumference(String tex){
|
||||
textures[1] = tex;
|
||||
textures[2] = tex;
|
||||
textures[3] = tex;
|
||||
textures[4] = tex;
|
||||
}
|
||||
public void setSides(String tex){
|
||||
textures[2] = tex;
|
||||
textures[4] = tex;
|
||||
}
|
||||
public void setTop(String tex){
|
||||
textures[0] = tex;
|
||||
}
|
||||
|
||||
public void setFront(String tex){
|
||||
textures[1] = tex;
|
||||
}
|
||||
|
||||
public void setRight(String tex){
|
||||
textures[2] = tex;
|
||||
}
|
||||
|
||||
public void setBack(String tex){
|
||||
textures[3] = tex;
|
||||
}
|
||||
|
||||
public void setLeft(String tex){
|
||||
textures[4] = tex;
|
||||
}
|
||||
|
||||
public void setBottom(String tex){
|
||||
textures[5] = tex;
|
||||
}
|
||||
public String getTop(){
|
||||
return textures[0];
|
||||
}
|
||||
|
||||
public String getFront(){
|
||||
return textures[1];
|
||||
}
|
||||
|
||||
public String getRight(){
|
||||
return textures[2];
|
||||
}
|
||||
|
||||
public String getBack(){
|
||||
return textures[3];
|
||||
}
|
||||
|
||||
public String getLeft(){
|
||||
return textures[4];
|
||||
}
|
||||
|
||||
public String getBottom(){
|
||||
return textures[5];
|
||||
}
|
||||
|
||||
public String[] getTextures() {
|
||||
return Arrays.copyOf(textures, 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
CubeTextureSet that = (CubeTextureSet) o;
|
||||
|
||||
if (!Arrays.equals(textures, that.textures)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(textures);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CubeTextureSet{" +
|
||||
"textures=" + Arrays.toString(textures) +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -54,22 +54,19 @@ public class MapChunk extends AbstractMapChunk {
|
|||
/**
|
||||
* Instantiates a new map chunk.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param light the primary data storage
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public MapChunk(byte[] light)
|
||||
throws IOException {
|
||||
loadBytes_(light);
|
||||
public MapChunk(byte[] light) {
|
||||
try {
|
||||
loadBytes_(light);
|
||||
} catch (IOException e){
|
||||
logger.fatal(Messages.getString("FAIL_BUILD_MAPCHUNK_FATAL"));
|
||||
throw new MosstestFatalDeathException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setManager(Void manager) {
|
||||
// This is a void here, ergo we can just return
|
||||
return;
|
||||
}
|
||||
|
||||
public void loadBytes_(byte[] light) throws IOException {
|
||||
//Arrays.copyOf(light, light.length);
|
||||
|
@ -200,7 +197,7 @@ public class MapChunk extends AbstractMapChunk {
|
|||
bos.flush();
|
||||
} catch (IOException e) {
|
||||
// should never happen
|
||||
logger.warn("IOException writing light chunk data");
|
||||
logger.warn(Messages.getString("LIGHT_DATA_IOEXCEPTION"));
|
||||
}
|
||||
|
||||
return bos.toByteArray();
|
||||
|
@ -216,9 +213,4 @@ public class MapChunk extends AbstractMapChunk {
|
|||
return this.writeLight(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBytes(byte[] buf) throws IOException{
|
||||
// delegate to internal implementation
|
||||
this.loadBytes_(buf);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package net.mosstest.scripting;
|
|||
|
||||
// TODO: Auto-generated Javadoc
|
||||
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
|
@ -172,7 +174,7 @@ public class MapNode {
|
|||
* @param texture the texture to use for each side
|
||||
* @param lightEmission the light emission
|
||||
*/
|
||||
public MapNode(String nodeName, String userFacingName, String texture,
|
||||
public MapNode(@NonNls String nodeName, String userFacingName, @NonNls String texture,
|
||||
int lightEmission) {
|
||||
this.nodeparams = new DefaultNodeParams();
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.mosstest.scripting;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
|
@ -21,8 +22,8 @@ public class Messages {
|
|||
*
|
||||
* @param identifier the identifier
|
||||
*/
|
||||
public static void changeLanguage(String identifier) {
|
||||
resBundle = ResourceBundle.getBundle(BUNDLE_NAME + "." + identifier);
|
||||
public static void changeLanguage(Locale identifier) {
|
||||
resBundle = ResourceBundle.getBundle(BUNDLE_NAME, identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package net.mosstest.scripting;
|
||||
|
||||
import net.mosstest.servercore.AbstractByteArrayStorable;
|
||||
import net.mosstest.servercore.ItemManager;
|
||||
import net.mosstest.servercore.MosstestFatalDeathException;
|
||||
import net.mosstest.servercore.serialization.IByteArrayWriteable;
|
||||
import net.mosstest.servercore.serialization.IManaged;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -11,7 +13,7 @@ import java.io.*;
|
|||
/**
|
||||
* The Class MossInventory.
|
||||
*/
|
||||
public class MossInventory extends AbstractByteArrayStorable<ItemManager> {
|
||||
public class MossInventory implements IByteArrayWriteable, IManaged<ItemManager> {
|
||||
|
||||
private ItemManager im;
|
||||
|
||||
|
@ -65,7 +67,8 @@ public class MossInventory extends AbstractByteArrayStorable<ItemManager> {
|
|||
bos.flush();
|
||||
} catch (IOException e) {
|
||||
// This should never happen in real life
|
||||
logger.error("IOException serializing an inventory. This should not happen, if it does a bug should be filed");
|
||||
logger.fatal(Messages.getString("INV_IOEXCEPTION_FATAL"));
|
||||
throw new MosstestFatalDeathException(e);
|
||||
}
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
@ -94,7 +97,7 @@ public class MossInventory extends AbstractByteArrayStorable<ItemManager> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void setManager(ItemManager manager) {
|
||||
public void setManager(ItemManager manager) {
|
||||
this.im = manager;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ package net.mosstest.scripting;
|
|||
// TODO: Auto-generated Javadoc
|
||||
|
||||
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
/**
|
||||
* The Class MossItem.
|
||||
*/
|
||||
|
@ -36,6 +38,7 @@ public class MossItem {
|
|||
|
||||
final String displayName;
|
||||
|
||||
@NonNls
|
||||
final String internalName;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.mosstest.scripting;
|
||||
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
public class MossItemBuilder {
|
||||
private String invTex;
|
||||
private String wieldTex;
|
||||
|
@ -13,7 +15,7 @@ public class MossItemBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public MossItemBuilder setWieldTex(String wieldTex) {
|
||||
public MossItemBuilder setWieldTex(@NonNls String wieldTex) {
|
||||
this.wieldTex = wieldTex;
|
||||
return this;
|
||||
}
|
||||
|
@ -52,12 +54,12 @@ public class MossItemBuilder {
|
|||
return internalName;
|
||||
}
|
||||
|
||||
public MossItemBuilder setDisplayName(String displayName) {
|
||||
public MossItemBuilder setDisplayName(@NonNls String displayName) {
|
||||
this.displayName = displayName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MossItemBuilder setInternalName(String internalName) {
|
||||
public MossItemBuilder setInternalName(@NonNls String internalName) {
|
||||
this.internalName = internalName;
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -1,320 +1,343 @@
|
|||
package net.mosstest.scripting;
|
||||
|
||||
import net.mosstest.scripting.events.IMossEvent;
|
||||
import net.mosstest.scripting.handlers.MossEventHandler;
|
||||
import net.mosstest.scripting.handlers.MossNodeChangeHandler;
|
||||
import net.mosstest.servercore.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* This class is used by scripts and script-facing portions of Mosstest. Methods
|
||||
* restricted to be called from trusted Java-side shall pass a
|
||||
* {@link ScriptSandboxBorderToken}. Each event fired will run in the thread
|
||||
* pool. All requests via this API need not concern themselves with threading as
|
||||
* everything is handled by Mosstest itself.
|
||||
* <p/>
|
||||
* The event handlers called are the ones defined via this class's registerOnFoo
|
||||
* methods, followed by any handlers defined in an instance of NodeParams via an
|
||||
* anonymous inner class, and finally with the default handler.
|
||||
* <p/>
|
||||
* The order in which handlers registered here are called is undefined due to
|
||||
* the undefined order of scripts being loaded. Generally, this is planned to
|
||||
* occur in an order based on the SHA512 hash of the script. Comments with dummy
|
||||
* information may be used by the script author to attempt to set the position
|
||||
* of a script in the execution order via manipulating the hash. Handlers of the
|
||||
* same types within the same script are guaranteed to be called in order.
|
||||
* <p/>
|
||||
* An event handler may interrupt handling of the event so that no further event
|
||||
* handlers nor the default are ever called, by returning the proper boolean value
|
||||
*
|
||||
* @author rarkenin
|
||||
* @version 0.0
|
||||
* @since 0.0
|
||||
*/
|
||||
public class MossScriptEnv {
|
||||
|
||||
public void registerNodeChangeHandler(MossNodeChangeHandler h) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private HashMap<Class<? extends IMossEvent>, ArrayList<MossEventHandler>> eventHandlers;
|
||||
|
||||
private ScriptableDatabase db;
|
||||
|
||||
private MapCache nc;
|
||||
|
||||
private FuturesProcessor fp;
|
||||
|
||||
private INodeManager nm;
|
||||
|
||||
|
||||
/**
|
||||
* Sends a chat message to a player.
|
||||
*
|
||||
* @param recipient A {@link Player} object representing the recipient. A Player
|
||||
* object may be constructed with
|
||||
* {@link MossScriptEnv#getPlayerByName(String)}.
|
||||
* @param from A player object representing the sender. A Player object may
|
||||
* be constructed with
|
||||
* {@link MossScriptEnv#getPlayerByName(String)}. If null a
|
||||
* message is sent showing to users as having been sent by the
|
||||
* server with the prefix <code>[*] Server:</code>
|
||||
* @param message A string representing the message that shall be sent to the
|
||||
* specified recipient.
|
||||
*/
|
||||
public void sendChatMessage(Player recipient, Player from, String message) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a chat message to all players.
|
||||
*
|
||||
* @param from A player object representing the sender. A Player object may
|
||||
* be constructed with
|
||||
* {@link MossScriptEnv#getPlayerByName(String)}. If null a
|
||||
* message is sent showing to users as having been sent by the
|
||||
* server with the prefix <code>[*] Server:</code>
|
||||
* @param message A string representing the message that shall be sent to the
|
||||
* specified recipient.
|
||||
*/
|
||||
public void sendChatAll(Player from, String message) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the health on an entity or player.
|
||||
*
|
||||
* @param p The player to set health on.
|
||||
* @param health A positive integer representing the amount of health to set.
|
||||
*/
|
||||
public void setHp(Player p, int health) {
|
||||
// TODO Once we have players doing stuff
|
||||
}
|
||||
|
||||
/**
|
||||
* Damages the tool of a player corresponding to a dig. The player's
|
||||
* currently selected tool is damaged.
|
||||
*
|
||||
* @param actor The player that is digging a node.
|
||||
* @param nd The node dug.
|
||||
* @throws MossScriptException Thrown if the current tool cannot be used to dig the node.
|
||||
*/
|
||||
public void damageTool(Player actor, MapNode nd) throws MossScriptException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives a player an item. The item stack will be added to the player's
|
||||
* default inventory, adding to the first available partial stack. If no
|
||||
* partial stacks are available the item is added to the first open slot in
|
||||
* the inventory.
|
||||
*
|
||||
* @param player the player
|
||||
* @param item the item
|
||||
* @return True if the item could be added, false if the item could not be
|
||||
* added due to insufficient space.
|
||||
*/
|
||||
public boolean givePlayer(Player player, MossItem.Stack item) {
|
||||
MossInventory mi = player.getInventory("default", 4, 8, 128);
|
||||
|
||||
// use side effect
|
||||
return (mi.addItem(item) == item.amount);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a node of the world to a given type. This cannot be called on a
|
||||
* NodePosition with an existing solid node; use
|
||||
* {@link #removeNode(NodePosition)} first.
|
||||
*
|
||||
* @param pos The position at which to set a node.
|
||||
* @param node The node to place at that position.
|
||||
*/
|
||||
public void setNode(NodePosition pos, MapNode node) throws MapGeneratorException {
|
||||
MapChunk chk = this.nc.getChunkNoGenerate(pos.chunk);
|
||||
if (chk == null)
|
||||
return;
|
||||
if (!(this.nm.containsNode(node) || node instanceof IDynamicNode))
|
||||
throw new IllegalArgumentException("The mapnode passed is not contained in the world node manager");
|
||||
|
||||
chk.setNode(pos.xl, pos.yl, pos.zl, node.getNodeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a node, setting it to air. This may be called on a NodePosition
|
||||
* with an existing solid node.
|
||||
*
|
||||
* @param pos The NodePosition at which to remove the node.
|
||||
*/
|
||||
public void removeNode(NodePosition pos) throws MapGeneratorException {
|
||||
MapChunk chk = this.nc.getChunkNoGenerate(pos.chunk);
|
||||
if (chk == null)
|
||||
return;
|
||||
chk.setNode(pos.xl, pos.yl, pos.zl, this.nm.getNode("mg:air") //$NON-NLS-1$
|
||||
.getNodeId());
|
||||
this.nc.setChunk(pos.chunk, chk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MapNode at a certain location.
|
||||
*
|
||||
* @param pos The location at which to get the node
|
||||
* @return A MapNode object representing the node at that location.
|
||||
* @throws MapGeneratorException the map generator exception
|
||||
*/
|
||||
public MapNode getNode(NodePosition pos) throws MapGeneratorException {
|
||||
return this.nm.getNode((short) this.nc.getChunk(pos.chunk).getNodeId(
|
||||
pos.xl, pos.yl, pos.zl));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a mapnode in the world, allowing it to be placed.
|
||||
* @param nd
|
||||
* @throws MossWorldLoadException
|
||||
*/
|
||||
public void registerNode(MapNode nd) throws MossWorldLoadException {
|
||||
this.nm.putNode(nd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new liquid in the node manager, generating intermediates as needed.
|
||||
*
|
||||
* @param sysname The name such as default:lava to set. The prefix mg: is used
|
||||
* for mapgen-specific nodes, and should be done by creating a
|
||||
* node with a different prefix and aliasing mg:foo to it.
|
||||
* @param userFacingName The name to display in the UI, such as Lava or Iron Ore
|
||||
* @param params An implementation of the {@link LiquidNodeParams} interface
|
||||
* detailing the action of the node. {@link LiquidSourceNodeParams} and
|
||||
* {@link LiquidFlowingNodeParams} are valid for liquid sources and flowing liquid nodes,
|
||||
* respectively.
|
||||
* @param flowParams the source params
|
||||
* @param textures A string stating the filename of the textures image.
|
||||
* @param light The amount of light from 0 to 255 to be emitted.
|
||||
* @return The MapNode object that has been created and added to the
|
||||
* manager.
|
||||
* @throws MossWorldLoadException If an exception occurs during the execution of the
|
||||
* registering.
|
||||
*/
|
||||
public LiquidNode registerLiquid(String sysname, String userFacingName,
|
||||
LiquidNodeParams params, LiquidNodeParams flowParams,
|
||||
String textures, int light) throws MossWorldLoadException {
|
||||
LiquidNode nd = new LiquidNode(params, textures, sysname,
|
||||
userFacingName, light);
|
||||
this.nm.putNode(nd);
|
||||
nd.level = 0;
|
||||
for (int i = 1; i < 8; i++) {
|
||||
LiquidNode innerNd = new LiquidNode(flowParams, textures, sysname
|
||||
+ "$LEVEL$" + i, userFacingName, light); //$NON-NLS-1$
|
||||
innerNd.setByBounds(-.5f, .5f, -.5f, .5f, -.5f, (i / 8f) - 0.5f);
|
||||
nd.liquidLevels[i] = innerNd;
|
||||
innerNd.liquidLevels = nd.liquidLevels;
|
||||
innerNd.level = i;
|
||||
this.nm.putNode(innerNd);
|
||||
}
|
||||
nd.liquidLevels[0] = nd;
|
||||
return nd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a node alias. Since the map generator and scripts work via
|
||||
* string names, registering an alias of mg:dirt to myscript:specialdirt
|
||||
* will cause a mapgen that recognizes mg:dirt as a generated element to use
|
||||
* specialdirt for that.
|
||||
*
|
||||
* @param alias The alias to create, i.e. mg:dirt
|
||||
* @param dst The existing node to set as the alias target, i.e
|
||||
* myscript:specialdirt. This element must already exist.
|
||||
*/
|
||||
public void registerNodeAlias(String alias, String dst) {
|
||||
this.nm.putNodeAlias(alias, dst);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the inv by name.
|
||||
*
|
||||
* @param player the player
|
||||
* @param name the name
|
||||
* @return the inv by name
|
||||
*/
|
||||
public MossInventory getInvByName(Player player, String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the inv by name.
|
||||
*
|
||||
* @param p the p
|
||||
* @param name the name
|
||||
* @return the moss inventory
|
||||
*/
|
||||
public MossInventory createInvByName(Player p, String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player by name.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the player by name
|
||||
*/
|
||||
public Player getPlayerByName(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node by name.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the node by name
|
||||
*/
|
||||
public MapNode getNodeByName(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the db.
|
||||
*
|
||||
* @return the db
|
||||
*/
|
||||
public ScriptableDatabase getDb() {
|
||||
return this.db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new moss script env.
|
||||
*
|
||||
* @param db the db
|
||||
* @param nc the nc
|
||||
* @param fp the fp
|
||||
* @param nm the nm
|
||||
*/
|
||||
public MossScriptEnv(ScriptableDatabase db, MapCache nc,
|
||||
FuturesProcessor fp, INodeManager nm) {
|
||||
this.db = db;
|
||||
this.nc = nc;
|
||||
this.fp = fp;
|
||||
this.nm = nm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the futures processor.
|
||||
*
|
||||
* @return the futures processor
|
||||
*/
|
||||
public FuturesProcessor getFuturesProcessor() {
|
||||
return this.fp;
|
||||
}
|
||||
|
||||
public ArrayList<MossEventHandler> getEventHandlers(
|
||||
Class<? extends IMossEvent> class1) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
package net.mosstest.scripting;
|
||||
|
||||
import net.mosstest.scripting.events.IMossEvent;
|
||||
import net.mosstest.scripting.handlers.MossEventHandler;
|
||||
import net.mosstest.scripting.handlers.MossNodeChangeHandler;
|
||||
import net.mosstest.servercore.*;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is used by scripts and script-facing portions of Mosstest. Methods
|
||||
* restricted to be called from trusted Java-side shall pass a
|
||||
* {@link ScriptSandboxBorderToken}. Each event fired will run in the thread
|
||||
* pool. All requests via this API need not concern themselves with threading as
|
||||
* everything is handled by Mosstest itself.
|
||||
* <p>
|
||||
* The event handlers called are the ones defined via this class's registerOnFoo
|
||||
* methods, followed by any handlers defined in an instance of NodeParams via an
|
||||
* anonymous inner class, and finally with the default handler.
|
||||
* <p>
|
||||
* The order in which handlers registered here are called is undefined due to
|
||||
* the undefined order of scripts being loaded. Generally, this is planned to
|
||||
* occur in an order based on the SHA512 hash of the script. Comments with dummy
|
||||
* information may be used by the script author to attempt to set the position
|
||||
* of a script in the execution order via manipulating the hash. Handlers of the
|
||||
* same types within the same script are guaranteed to be called in order.
|
||||
* <p>
|
||||
* An event handler may interrupt handling of the event so that no further event
|
||||
* handlers nor the default are ever called, by returning the proper boolean value
|
||||
*
|
||||
* @author rarkenin
|
||||
* @version 0.0
|
||||
* @since 0.0
|
||||
*/
|
||||
public class MossScriptEnv {
|
||||
|
||||
public void registerNodeChangeHandler(MossNodeChangeHandler h) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private HashMap<Class<? extends IMossEvent>, ArrayList<MossEventHandler>> eventHandlers;
|
||||
|
||||
private ScriptableDatabase db;
|
||||
|
||||
private MapCache nc;
|
||||
|
||||
private FuturesProcessor fp;
|
||||
|
||||
private INodeManager nm;
|
||||
|
||||
|
||||
/**
|
||||
* Sends a chat message to a player.
|
||||
*
|
||||
* @param recipient A {@link Player} object representing the recipient. A Player
|
||||
* object may be constructed with
|
||||
* {@link MossScriptEnv#getPlayerByName(String)}.
|
||||
* @param from A player object representing the sender. A Player object may
|
||||
* be constructed with
|
||||
* {@link MossScriptEnv#getPlayerByName(String)}. If null a
|
||||
* message is sent showing to users as having been sent by the
|
||||
* server with the prefix <code>[*] Server:</code>
|
||||
* @param message A string representing the message that shall be sent to the
|
||||
* specified recipient.
|
||||
*/
|
||||
public void sendChatMessage(Player recipient, Player from, String message) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a chat message to all players.
|
||||
*
|
||||
* @param from A player object representing the sender. A Player object may
|
||||
* be constructed with
|
||||
* {@link MossScriptEnv#getPlayerByName(String)}. If null a
|
||||
* message is sent showing to users as having been sent by the
|
||||
* server with the prefix <code>[*] Server:</code>
|
||||
* @param message A string representing the message that shall be sent to the
|
||||
* specified recipient.
|
||||
*/
|
||||
public void sendChatAll(Player from, String message) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the health on an entity or player.
|
||||
*
|
||||
* @param p The player to set health on.
|
||||
* @param health A positive integer representing the amount of health to set.
|
||||
*/
|
||||
public void setHp(Player p, int health) {
|
||||
// TODO Once we have players doing stuff
|
||||
}
|
||||
|
||||
/**
|
||||
* Damages the tool of a player corresponding to a dig. The player's
|
||||
* currently selected tool is damaged.
|
||||
*
|
||||
* @param actor The player that is digging a node.
|
||||
* @param nd The node dug.
|
||||
* @throws MossScriptException Thrown if the current tool cannot be used to dig the node.
|
||||
*/
|
||||
public void damageTool(Player actor, MapNode nd) throws MossScriptException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives a player an item. The item stack will be added to the player's
|
||||
* default inventory, adding to the first available partial stack. If no
|
||||
* partial stacks are available the item is added to the first open slot in
|
||||
* the inventory.
|
||||
*
|
||||
* @param player the player
|
||||
* @param item the item
|
||||
* @return True if the item could be added, false if the item could not be
|
||||
* added due to insufficient space.
|
||||
*/
|
||||
public boolean givePlayer(Player player, MossItem.Stack item) {
|
||||
MossInventory mi = player.getInventory("default", 4, 8, 128);
|
||||
|
||||
// use side effect
|
||||
return (mi.addItem(item) == item.amount);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a node of the world to a given type. This cannot be called on a
|
||||
* NodePosition with an existing solid node; use
|
||||
* {@link #removeNode(NodePosition)} first.
|
||||
*
|
||||
* @param pos The position at which to set a node.
|
||||
* @param node The node to place at that position.
|
||||
*/
|
||||
public void setNode(NodePosition pos, MapNode node) throws MapGeneratorException {
|
||||
MapChunk chk = this.nc.getChunkNoGenerate(pos.chunk);
|
||||
if (chk == null)
|
||||
return;
|
||||
if (!(this.nm.containsNode(node) || node instanceof IDynamicNode))
|
||||
throw new IllegalArgumentException("The mapnode passed is not contained in the world node manager");
|
||||
|
||||
chk.setNode(pos.xl, pos.yl, pos.zl, node.getNodeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a node, setting it to air. This may be called on a NodePosition
|
||||
* with an existing solid node.
|
||||
*
|
||||
* @param pos The NodePosition at which to remove the node.
|
||||
*/
|
||||
public void removeNode(NodePosition pos) throws MapGeneratorException {
|
||||
MapChunk chk = this.nc.getChunkNoGenerate(pos.chunk);
|
||||
if (chk == null)
|
||||
return;
|
||||
chk.setNode(pos.xl, pos.yl, pos.zl, this.nm.getNode("mg:air") //$NON-NLS-1$
|
||||
.getNodeId());
|
||||
this.nc.setChunk(pos.chunk, chk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MapNode at a certain location.
|
||||
*
|
||||
* @param pos The location at which to get the node
|
||||
* @return A MapNode object representing the node at that location.
|
||||
* @throws MapGeneratorException the map generator exception
|
||||
*/
|
||||
public MapNode getNode(NodePosition pos) throws MapGeneratorException {
|
||||
return this.nm.getNode((short) this.nc.getChunk(pos.chunk).getNodeId(
|
||||
pos.xl, pos.yl, pos.zl));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a mapnode in the world, allowing it to be placed.
|
||||
*
|
||||
* @param nd
|
||||
* @throws MossWorldLoadException
|
||||
*/
|
||||
public void registerNode(MapNode nd) throws MossWorldLoadException {
|
||||
this.nm.putNode(nd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new liquid in the node manager, generating intermediates as needed.
|
||||
*
|
||||
* @param sysname The name such as default:lava to set. The prefix mg: is used
|
||||
* for mapgen-specific nodes, and should be done by creating a
|
||||
* node with a different prefix and aliasing mg:foo to it.
|
||||
* @param userFacingName The name to display in the UI, such as Lava or Iron Ore
|
||||
* @param params An implementation of the {@link LiquidNodeParams} interface
|
||||
* detailing the action of the node. {@link LiquidSourceNodeParams} and
|
||||
* {@link LiquidFlowingNodeParams} are valid for liquid sources and flowing liquid nodes,
|
||||
* respectively.
|
||||
* @param flowParams the source params
|
||||
* @param textures A string stating the filename of the textures image.
|
||||
* @param light The amount of light from 0 to 255 to be emitted.
|
||||
* @return The MapNode object that has been created and added to the
|
||||
* manager.
|
||||
* @throws MossWorldLoadException If an exception occurs during the execution of the
|
||||
* registering.
|
||||
*/
|
||||
public LiquidNode registerLiquid(@NonNls String sysname, String userFacingName,
|
||||
LiquidNodeParams params, LiquidNodeParams flowParams,
|
||||
String textures, int light) throws MossWorldLoadException {
|
||||
LiquidNode nd = new LiquidNode(params, textures, sysname,
|
||||
userFacingName, light);
|
||||
this.nm.putNode(nd);
|
||||
nd.level = 0;
|
||||
for (int i = 1; i < 8; i++) {
|
||||
LiquidNode innerNd = new LiquidNode(flowParams, textures, sysname
|
||||
+ "$LEVEL$" + i, userFacingName, light); //$NON-NLS-1$
|
||||
innerNd.setByBounds(-.5f, .5f, -.5f, .5f, -.5f, (i / 8f) - 0.5f);
|
||||
nd.liquidLevels[i] = innerNd;
|
||||
innerNd.liquidLevels = nd.liquidLevels;
|
||||
innerNd.level = i;
|
||||
this.nm.putNode(innerNd);
|
||||
}
|
||||
nd.liquidLevels[0] = nd;
|
||||
return nd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a node alias. Since the map generator and scripts work via
|
||||
* string names, registering an alias of mg:dirt to myscript:specialdirt
|
||||
* will cause a mapgen that recognizes mg:dirt as a generated element to use
|
||||
* specialdirt for that.
|
||||
*
|
||||
* @param alias The alias to create, i.e. mg:dirt
|
||||
* @param dst The existing node to set as the alias target, i.e
|
||||
* myscript:specialdirt. This element must already exist.
|
||||
*/
|
||||
public void registerNodeAlias(String alias, String dst) {
|
||||
this.nm.putNodeAlias(alias, dst);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the inv by name.
|
||||
*
|
||||
* @param player the player
|
||||
* @param name the name
|
||||
* @return the inv by name
|
||||
*/
|
||||
public MossInventory getInvByName(Player player, String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the inv by name.
|
||||
*
|
||||
* @param p the p
|
||||
* @param name the name
|
||||
* @return the moss inventory
|
||||
*/
|
||||
public MossInventory createInvByName(Player p, String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player by name.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the player by name
|
||||
*/
|
||||
public Player getPlayerByName(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node by name.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the node by name
|
||||
*/
|
||||
public MapNode getNodeByName(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the db.
|
||||
*
|
||||
* @return the db
|
||||
*/
|
||||
public ScriptableDatabase getDb() {
|
||||
return this.db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new moss script env.
|
||||
*
|
||||
* @param db the db
|
||||
* @param nc the nc
|
||||
* @param fp the fp
|
||||
* @param nm the nm
|
||||
*/
|
||||
public MossScriptEnv(ScriptableDatabase db, MapCache nc,
|
||||
FuturesProcessor fp, INodeManager nm) {
|
||||
this.db = db;
|
||||
this.nc = nc;
|
||||
this.fp = fp;
|
||||
this.nm = nm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the futures processor.
|
||||
*
|
||||
* @return the futures processor
|
||||
*/
|
||||
public FuturesProcessor getFuturesProcessor() {
|
||||
return this.fp;
|
||||
}
|
||||
|
||||
private HashMap<Class<? extends IMossEvent>, List<MossEventHandler>> handlers = new HashMap<>();
|
||||
|
||||
public List<MossEventHandler> getEventHandlers(
|
||||
Class<? extends IMossEvent> clazz) {
|
||||
List<MossEventHandler> l = Collections.unmodifiableList(handlers.get(clazz));
|
||||
if (l == null) {
|
||||
handlers.put(clazz, new ArrayList<MossEventHandler>());
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
return l;
|
||||
|
||||
}
|
||||
|
||||
public void registerHandler(MossEventHandler handler, Class<? extends IMossEvent> clazz) {
|
||||
List<MossEventHandler> l = handlers.get(clazz);
|
||||
if (l == null) {
|
||||
l = new ArrayList<MossEventHandler>();
|
||||
handlers.put(clazz, l);
|
||||
l.add(handler);
|
||||
return;
|
||||
}
|
||||
l.add(handler);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
|
||||
import net.mosstest.servercore.PlayerCommunicator;
|
||||
import net.mosstest.servercore.RenderProcessor;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
|
||||
|
@ -144,7 +145,7 @@ public class Player {
|
|||
* @param maxStack the max stack
|
||||
* @return the moss inventory
|
||||
*/
|
||||
public MossInventory getInventory(String name, int rows, int cols,
|
||||
public MossInventory getInventory(@NonNls String name, int rows, int cols,
|
||||
int maxStack) {
|
||||
// todo inventory caching
|
||||
MossInventory inv = inventories.get(name);
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
package net.mosstest.scripting;
|
||||
|
||||
import net.mosstest.servercore.AbstractByteArrayStorable;
|
||||
|
||||
import net.mosstest.servercore.serialization.IByteArrayWriteable;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
* The Class Position.
|
||||
*/
|
||||
public class Position extends AbstractByteArrayStorable<Void>{
|
||||
*/
|
||||
public class Position implements IByteArrayWriteable{
|
||||
public static final int SERIALIZED_LENGTH = 16;
|
||||
@Override
|
||||
@NonNls
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Position [x=" + x + ", y=" + y + ", z=" + z + ", realm="
|
||||
+ realm + ", hashCode()=" + hashCode() + "]";
|
||||
|
@ -23,7 +25,7 @@ public class Position extends AbstractByteArrayStorable<Void>{
|
|||
|
||||
/** The realm. */
|
||||
public int realm;
|
||||
|
||||
|
||||
transient boolean isValid = true;
|
||||
|
||||
/**
|
||||
|
@ -47,15 +49,10 @@ public class Position extends AbstractByteArrayStorable<Void>{
|
|||
*
|
||||
* @param bytes the bytes
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public Position(byte[] bytes) throws IllegalArgumentException {
|
||||
// ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
|
||||
// DataInputStream dis = new DataInputStream(bis);
|
||||
loadBytes(bytes);
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void loadBytes(byte[] bytes) {
|
||||
|
||||
public Position(byte[] bytes) {
|
||||
if (bytes.length != 16)
|
||||
throw new IllegalArgumentException(
|
||||
"Input array is not 16 elements long.");
|
||||
|
@ -73,14 +70,10 @@ public class Position extends AbstractByteArrayStorable<Void>{
|
|||
this.isValid = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void setManager(Void manager) {
|
||||
// no-op with Void
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
|
@ -142,7 +135,7 @@ public class Position extends AbstractByteArrayStorable<Void>{
|
|||
|
||||
(byte) this.x, (byte) this.y, (byte) this.z };
|
||||
assert(buf.length==Position.SERIALIZED_LENGTH);
|
||||
return buf;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package net.mosstest.scripting;
|
||||
|
||||
import static org.fusesource.leveldbjni.JniDBFactory.asString;
|
||||
import static org.fusesource.leveldbjni.JniDBFactory.bytes;
|
||||
import static org.fusesource.leveldbjni.JniDBFactory.factory;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import net.mosstest.servercore.serialization.IByteArrayWriteable;
|
||||
import org.iq80.leveldb.DB;
|
||||
import org.iq80.leveldb.Options;
|
||||
|
||||
|
@ -48,16 +48,14 @@ public class ScriptableDatabase {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* The Class DBase.
|
||||
*/
|
||||
|
||||
public class DBase {
|
||||
// this class will contain a database that scripts may access.
|
||||
/** The inner db. */
|
||||
private final DB innerDb;
|
||||
|
||||
/**
|
||||
* Instantiates a new d base.
|
||||
* Instantiates a new database.
|
||||
*
|
||||
* @param innerDb the inner db
|
||||
* @param name the name
|
||||
|
@ -66,116 +64,21 @@ public class ScriptableDatabase {
|
|||
this.innerDb = innerDb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a piece of string data with a string key, or <code>null</code> if
|
||||
* the datum cannot be found. String keys are exclusive from all other
|
||||
* key types.
|
||||
*
|
||||
* @param key the key
|
||||
* @return A string representing the stored data.
|
||||
*/
|
||||
public String getDatum(String key) {
|
||||
byte[] keyBytes = bytes("string::" + key); //$NON-NLS-1$
|
||||
byte[] dataBytes = this.innerDb.get(keyBytes);
|
||||
return (dataBytes == null) ? null : asString(dataBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a datum with a generic string key, overwriting as necessary.
|
||||
*
|
||||
* @param key
|
||||
* The string key.
|
||||
* @param data
|
||||
* The data to put.
|
||||
*/
|
||||
public void putDatum(String key, String data) {
|
||||
this.innerDb.put(bytes("string::" + key), bytes(data)); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a piece of string data with a position and string key, or
|
||||
* <code>null</code> if the datum cannot be found. Position keys are
|
||||
* exclusive from all other key types.
|
||||
*
|
||||
* @param pos the pos
|
||||
* @param key the key
|
||||
* @return The found data.
|
||||
*/
|
||||
public String getPositionDatum(NodePosition pos, String key) {
|
||||
byte[] keyBytes = ArrayUtils.addAll(bytes("npos::"), //$NON-NLS-1$
|
||||
ArrayUtils.addAll(pos.toBytes(), bytes("str::" + key))); //$NON-NLS-1$
|
||||
byte[] dataBytes = this.innerDb.get(keyBytes);
|
||||
return (dataBytes == null) ? null : asString(dataBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a datum with a position and string key, overwriting as necessary.
|
||||
*
|
||||
* @param pos
|
||||
* The position portion of the key.
|
||||
* @param key
|
||||
* The string key.
|
||||
* @param data
|
||||
* The data to put.
|
||||
*/
|
||||
public void putPositionDatum(NodePosition pos, String key, String data) {
|
||||
byte[] keyBytes = ArrayUtils.addAll(bytes("npos::"), //$NON-NLS-1$
|
||||
ArrayUtils.addAll(pos.toBytes(), bytes("str::" + key))); //$NON-NLS-1$
|
||||
byte[] dataBytes = bytes(data);
|
||||
this.innerDb.put(keyBytes, dataBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string of data associated with a chunk and string key, or
|
||||
* <code>null</code> if not found.
|
||||
*
|
||||
* @param pos The chunk position.
|
||||
* @param key The string key.
|
||||
* @return The found data.
|
||||
*/
|
||||
public String getChunkDatum(Position pos, String key) {
|
||||
byte[] keyBytes = ArrayUtils.addAll(bytes("cpos::"), //$NON-NLS-1$
|
||||
ArrayUtils.addAll(pos.toBytes(), bytes("str::" + key))); //$NON-NLS-1$
|
||||
byte[] dataBytes = this.innerDb.get(keyBytes);
|
||||
return (dataBytes == null) ? null : asString(dataBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a string of data keyed with a string and chunk.
|
||||
* @param pos The chunk position.
|
||||
* @param key The string key.
|
||||
* @param data The data to put.
|
||||
*/
|
||||
public void putChunkDatum(Position pos, String key, String data) {
|
||||
byte[] keyBytes = ArrayUtils.addAll(bytes("cpos::"), //$NON-NLS-1$
|
||||
ArrayUtils.addAll(pos.toBytes(), bytes("str::" + key))); //$NON-NLS-1$
|
||||
byte[] dataBytes = bytes(data);
|
||||
this.innerDb.put(keyBytes, dataBytes);
|
||||
}
|
||||
/**
|
||||
* Gets a string of data associated with a player and string key, or
|
||||
* <code>null</code> if not found.
|
||||
*
|
||||
* @param p The player.
|
||||
* @param key The string key.
|
||||
* @return The found data.
|
||||
*/
|
||||
public String getPlayerDatum(Player p, String key) {
|
||||
byte[] keyBytes = bytes("plr::" + p.name + "str::" + key); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
byte[] dataBytes = this.innerDb.get(keyBytes);
|
||||
return (dataBytes == null) ? null : asString(dataBytes);
|
||||
}
|
||||
/**
|
||||
* Puts a string of data keyed with a string and player.
|
||||
* @param p The player.
|
||||
* @param key The string key.
|
||||
* @param data The data to put.
|
||||
*/
|
||||
public void putPlayerDatum(Player p, String key, String data) {
|
||||
byte[] keyBytes = bytes("plr::" + p.name + "str::" + key); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
byte[] dataBytes = bytes(data);
|
||||
this.innerDb.put(keyBytes, dataBytes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class DBKey implements IByteArrayWriteable {
|
||||
private List<IByteArrayWriteable> qualifiers;
|
||||
|
||||
@Override
|
||||
public byte[] toBytes() {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import net.mosstest.scripting.MapNode;
|
|||
import net.mosstest.scripting.MossItem;
|
||||
import net.mosstest.scripting.NodePosition;
|
||||
import net.mosstest.scripting.Player;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
/**
|
||||
|
@ -88,4 +89,43 @@ public class MossNodeChangeEvent implements IMossEvent{
|
|||
this.wieldItem = wieldItem;
|
||||
}
|
||||
|
||||
@SuppressWarnings("HardCodedStringLiteral")
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("pl", pl)
|
||||
.append("pos", pos)
|
||||
.append("seqnum", seqnum)
|
||||
.append("type", type)
|
||||
.append("nodeBefore", nodeBefore)
|
||||
.append("wieldItem", wieldItem)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
MossNodeChangeEvent that = (MossNodeChangeEvent) o;
|
||||
|
||||
if (seqnum != that.seqnum) return false;
|
||||
if (nodeBefore != null ? !nodeBefore.equals(that.nodeBefore) : that.nodeBefore != null) return false;
|
||||
if (pl != null ? !pl.equals(that.pl) : that.pl != null) return false;
|
||||
if (pos != null ? !pos.equals(that.pos) : that.pos != null) return false;
|
||||
if (type != that.type) return false;
|
||||
if (wieldItem != null ? !wieldItem.equals(that.wieldItem) : that.wieldItem != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = pl != null ? pl.hashCode() : 0;
|
||||
result = 31 * result + (pos != null ? pos.hashCode() : 0);
|
||||
result = 31 * result + type.hashCode();
|
||||
result = 31 * result + (nodeBefore != null ? nodeBefore.hashCode() : 0);
|
||||
result = 31 * result + (wieldItem != null ? wieldItem.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
AntiCheatController.THREAD_NAME=anticheat
|
||||
MossEvent.MSG_CROSS_DMZ_SECURITY_WARNING=Attempt to access controlled resources in the script DMZ.
|
||||
ScriptableDatabase.DB_NAME_INVALID=Invalid database name.
|
||||
INV_IOEXCEPTION_FATAL=IOException serializing an inventory. THE WORLD IS GOING DOWN SHORTLY.
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
package net.mosstest.servercore;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class AbstractByteArrayStorable<M> {
|
||||
|
||||
|
||||
|
||||
public AbstractByteArrayStorable() {
|
||||
|
||||
}
|
||||
|
||||
public abstract byte[] toBytes();
|
||||
|
||||
public AbstractByteArrayStorable(byte[] buf) throws IOException{
|
||||
this.loadBytes(buf);
|
||||
}
|
||||
|
||||
public AbstractByteArrayStorable(byte[] buf, M manager) throws IOException{
|
||||
this.setManager(manager);
|
||||
this.loadBytes(buf);
|
||||
}
|
||||
|
||||
protected abstract void setManager(M manager);
|
||||
|
||||
|
||||
public abstract void loadBytes(byte[] buf) throws IOException;
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package net.mosstest.servercore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbstractMossScript {
|
||||
|
||||
protected AbstractMossScript(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@org.jetbrains.annotations.NonNls
|
||||
final String name;
|
||||
abstract void exec(ScriptEnv sEnv) throws IOException, MossWorldLoadException;
|
||||
|
||||
abstract IMossFile getInitFile() throws IOException;
|
||||
|
||||
abstract List<AbstractMossScript> getDependencies();
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof AbstractMossScript)) return false;
|
||||
|
||||
AbstractMossScript that = (AbstractMossScript) o;
|
||||
|
||||
if (!name.equals(that.name)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package net.mosstest.servercore;
|
|||
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import net.mosstest.scripting.MapNode;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -38,8 +39,14 @@ public abstract class AbstractNodeManager implements INodeManager {
|
|||
*/
|
||||
public static final MapNode MAPNODE_UNKNOWN;
|
||||
|
||||
@NonNls
|
||||
private static final String SYS_UNKNOWN = "sys:unknown";
|
||||
|
||||
@NonNls
|
||||
private static final String BUILTIN_UNKNOWN_TEXTURE = "builtin/unknown.png";
|
||||
|
||||
static {
|
||||
MAPNODE_UNKNOWN = new MapNode("sys:unknown", Messages.getString("AbstractNodeManager.DESC_UNKNOWN_NODE"), "builtin/unknown.png",
|
||||
MAPNODE_UNKNOWN = new MapNode(SYS_UNKNOWN, Messages.getString("AbstractNodeManager.DESC_UNKNOWN_NODE"), BUILTIN_UNKNOWN_TEXTURE,
|
||||
1); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
MAPNODE_UNKNOWN.setNodeId((short) -1);
|
||||
}
|
||||
|
|
|
@ -222,7 +222,7 @@ public class ClientNetworkingManager {
|
|||
}
|
||||
|
||||
}
|
||||
}, "ClientBulkRecv"); //$NON-NLS-1$
|
||||
}, "ClientFastRecv"); //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* The party quenched.
|
||||
|
@ -261,7 +261,7 @@ public class ClientNetworkingManager {
|
|||
if (magic == CommonNetworking.magic)
|
||||
sendAck(dos.readUnsignedShort());
|
||||
if (!(magic == CommonNetworking.magic || magic == CommonNetworking.magicNoAck)) {
|
||||
logger.warn("A packet was received with an invalid magic number and has been dropped.");
|
||||
logger.warn(Messages.getString("PACKET_INVALID_MAGIC"));
|
||||
continue recvLoop;
|
||||
}
|
||||
int length = dos.readUnsignedByte();
|
||||
|
@ -383,7 +383,7 @@ public class ClientNetworkingManager {
|
|||
Messages.getString("ClientNetworkingManager.ERR_NETWORK_TIMEOUT"), //$NON-NLS-1$
|
||||
Messages.getString("ClientNetworkingManager.DESC_NETWORK_TIMEOUT"), //$NON-NLS-1$
|
||||
true);
|
||||
logger.error("The connection to the server has timed out or otherwise failed.");
|
||||
logger.error(Messages.getString("SERVER_CONN_TIMEOUT"));
|
||||
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
package net.mosstest.servercore;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
/**
|
||||
* The Class EngineSettings.
|
||||
*/
|
||||
public class EngineSettings {
|
||||
private static final Logger logger = Logger.getLogger(EngineSettings.class);
|
||||
|
||||
/**
|
||||
* Gets the int.
|
||||
|
@ -13,7 +18,8 @@ public class EngineSettings {
|
|||
* @param def the def
|
||||
* @return the int
|
||||
*/
|
||||
public static int getInt(String name, int def){
|
||||
public static int getInt(@NonNls String name, int def){
|
||||
logger.error(Messages.getString("FIXME_MESSAGE"));
|
||||
if("forced".equals("false")){ //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return 0; //TODO this case
|
||||
}
|
||||
|
@ -28,6 +34,7 @@ public class EngineSettings {
|
|||
* @return the bool
|
||||
*/
|
||||
public static boolean getBool(String string, boolean def) {
|
||||
logger.error(Messages.getString("FIXME_MESSAGE"));
|
||||
if("forced".equals("false")){ //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return false; //TODO this case
|
||||
}
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
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.events.IMossEvent;
|
||||
import net.mosstest.scripting.events.MossNodeChangeEvent;
|
||||
import net.mosstest.scripting.events.ThreadStopEvent;
|
||||
import net.mosstest.scripting.handlers.MossEventHandler;
|
||||
import net.mosstest.scripting.handlers.MossNodeChangeHandler;
|
||||
import net.mosstest.servercore.MosstestSecurityManager.ThreadContext;
|
||||
import org.apache.commons.configuration.ConfigurationException;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
@ -21,9 +27,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.
|
||||
|
@ -79,7 +85,7 @@ public class EventProcessor {
|
|||
{// Section for actually handling the events
|
||||
if (myEvent instanceof ThreadStopEvent) {
|
||||
this.currentThreads.decrementAndGet();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
dispatchEvent(myEvent);
|
||||
}
|
||||
|
@ -87,14 +93,15 @@ public class EventProcessor {
|
|||
} catch (InterruptedException e) {
|
||||
// thread struck, shut down the operation.
|
||||
}
|
||||
logger.info("A thread is shutting down."); //$NON-NLS-1$
|
||||
this.currentThreads.decrementAndGet();
|
||||
|
||||
}
|
||||
logger.info("A thread is shutting down."); //$NON-NLS-1$
|
||||
this.currentThreads.decrementAndGet();
|
||||
|
||||
}
|
||||
|
||||
private void dispatchEvent(IMossEvent evt) {
|
||||
ArrayList<MossEventHandler> evtHandlerList = this.ev
|
||||
List<MossEventHandler> evtHandlerList = this.ev
|
||||
.getEventHandlers(evt.getClass());
|
||||
try {
|
||||
for (MossEventHandler ourHandler : evtHandlerList) {
|
||||
|
@ -104,8 +111,8 @@ public class EventProcessor {
|
|||
}
|
||||
DefaultEventHandlers.processEvent(evt, this.ev);
|
||||
} catch (MossScriptException | IllegalArgumentException e) {
|
||||
logger.warn(e.getClass().getName() + " upon processing event: "
|
||||
+ e.getMessage());
|
||||
logger.warn(MessageFormat.format(Messages.getString("EVENT_PROCESS_EXCEPTION"), e.getClass().getName(), evt.getClass().getName(), e.getLocalizedMessage()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,4 +226,6 @@ public class EventProcessor {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -22,8 +22,23 @@ public class FaceRenderer {
|
|||
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:
|
||||
break;
|
||||
case BOTTOM:
|
||||
break;
|
||||
case LEFT:
|
||||
break;
|
||||
case RIGHT:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void populateBuffers(Face f, float x, float y, float z, final float NODE_SIZE) {
|
||||
|
|
|
@ -38,7 +38,7 @@ public class FuturesProcessor {
|
|||
try {
|
||||
task = queue.take();
|
||||
} catch (InterruptedException e) {
|
||||
logger.error("InterruptedException in futures processor trying to take from queue.");
|
||||
logger.error(Messages.getString("FUTURES_QUEUE_INTERRUPTED"));
|
||||
Thread.currentThread().interrupt(); // in case caller requires detecting interrupts
|
||||
continue rLoop;
|
||||
}
|
||||
|
|
|
@ -16,4 +16,6 @@ public interface IFileManager {
|
|||
public Class<? extends AssetLocator> getAssetLocatorClass();
|
||||
|
||||
public List<? extends IMossFile> getFiles();
|
||||
|
||||
public AbstractMossScript getScript(final String name) throws IOException, MossWorldLoadException;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package net.mosstest.servercore;
|
||||
|
||||
import net.mosstest.scripting.Player;
|
||||
import net.mosstest.servercore.serialization.IByteArrayWriteable;
|
||||
import org.apache.commons.lang.NotImplementedException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class InventoryManager {
|
||||
public class PlayerKey extends AbstractByteArrayStorable<Void> {
|
||||
public class PlayerKey implements IByteArrayWriteable {
|
||||
private final Player player;
|
||||
|
||||
private final String inventory;
|
||||
|
@ -21,14 +22,8 @@ public class InventoryManager {
|
|||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setManager(Void manager) {
|
||||
// no-op as we have a void
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBytes(byte[] buf) throws IOException {
|
||||
throw new NotImplementedException("A player key cannot be created from a byte[]");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package net.mosstest.servercore;
|
|||
import net.mosstest.scripting.MapNode;
|
||||
import net.mosstest.scripting.MossItem;
|
||||
import net.mosstest.scripting.MossItemBuilder;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -26,6 +27,7 @@ public class ItemManager {
|
|||
/**
|
||||
* The unknown fallback item.
|
||||
*/
|
||||
@NonNls
|
||||
private final MossItem unknownFallbackItem = new MossItemBuilder().setInvTex("item_unknown.png").setWieldTex("sys_hand.png").setInvWeight(1).setStackMode(MossItem.StackMode.STACK_UNIT).setDisplayName("An unidentifiable item").setInternalName("sys:unknown").createMossItem();
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package net.mosstest.servercore;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import com.jme3.asset.AssetInfo;
|
||||
import com.jme3.asset.AssetKey;
|
||||
|
@ -10,47 +11,46 @@ import com.jme3.asset.AssetLocator;
|
|||
import com.jme3.asset.AssetManager;
|
||||
|
||||
public class LocalAssetLocator implements AssetLocator {
|
||||
private LocalFileManager lfm;
|
||||
private LocalFileManager lfm;
|
||||
|
||||
@Override
|
||||
public AssetInfo locate(AssetManager manager, AssetKey key) {
|
||||
if (this.lfm == null)
|
||||
this.lfm = LocalFileManager.getFileManager("scripts");
|
||||
if (this.lfm == null)
|
||||
this.lfm = LocalFileManager.scriptsInstance;
|
||||
try {
|
||||
return new LocalAssetInfo(manager, key,
|
||||
this.lfm.getFile(key.getName()));
|
||||
} catch (IOException ex) {
|
||||
throw new AssetLoadException("Failed to open file: "
|
||||
+ key.getName(), ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssetInfo locate(AssetManager manager, AssetKey key) {
|
||||
if (this.lfm == null)
|
||||
this.lfm = LocalFileManager.getFileManager("scripts");
|
||||
if (this.lfm == null)
|
||||
this.lfm = LocalFileManager.scriptsInstance;
|
||||
try {
|
||||
return new LocalAssetInfo(manager, key,
|
||||
this.lfm.getFile(key.getName()));
|
||||
} catch (IOException ex) {
|
||||
throw new AssetLoadException(MessageFormat.format(Messages.getString("FILE_OPEN_FAILED"),
|
||||
key.getName(), ex));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRootPath(String arg0) {
|
||||
this.lfm = LocalFileManager.getFileManager(arg0);
|
||||
}
|
||||
}
|
||||
|
||||
private static class LocalAssetInfo extends AssetInfo {
|
||||
@Override
|
||||
public void setRootPath(String arg0) {
|
||||
this.lfm = LocalFileManager.getFileManager(arg0);
|
||||
}
|
||||
|
||||
private LocalFile file;
|
||||
private static class LocalAssetInfo extends AssetInfo {
|
||||
|
||||
public LocalAssetInfo(AssetManager manager, AssetKey key, LocalFile file) {
|
||||
super(manager, key);
|
||||
this.file = file;
|
||||
}
|
||||
private LocalFile file;
|
||||
|
||||
@Override
|
||||
public InputStream openStream() {
|
||||
try {
|
||||
return this.file.getInputStream();
|
||||
} catch (IOException ex) {
|
||||
throw new AssetLoadException("Failed to open file: "
|
||||
+ this.file.getFilename(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
public LocalAssetInfo(AssetManager manager, AssetKey key, LocalFile file) {
|
||||
super(manager, key);
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream openStream() {
|
||||
try {
|
||||
return this.file.getInputStream();
|
||||
} catch (IOException ex) {
|
||||
throw new AssetLoadException(MessageFormat.format(Messages.getString("FILE_OPEN_FAILED"), this.file.getFilename()), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.apache.log4j.Logger;
|
|||
|
||||
import java.io.*;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
public class LocalFile implements IMossFile {
|
||||
|
||||
|
@ -47,9 +48,9 @@ public class LocalFile implements IMossFile {
|
|||
/ ((double) IMossFile.CHUNK_SIZE));
|
||||
try {
|
||||
this.sha256 = LocalFileManager.getHash(f);
|
||||
logger.info("Hashed " + f.getAbsolutePath() + " as " + this.sha256);
|
||||
logger.info(MessageFormat.format(Messages.getString("HASH_SUCCESS"), f.getAbsolutePath(), this.sha256));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
logger.error("Could not find algorithm SHA-256 while hashing " + f.getAbsolutePath());
|
||||
logger.error(MessageFormat.format(Messages.getString("ALGO_NOT_FOUND"), f.getAbsolutePath()));
|
||||
throw new IOException("Hashing failed while preparing file", e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,14 @@ package net.mosstest.servercore;
|
|||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.jme3.asset.AssetLocator;
|
||||
import org.apache.commons.configuration.ConfigurationException;
|
||||
import org.apache.commons.configuration.XMLConfiguration;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.io.filefilter.FileFilterUtils;
|
||||
import org.apache.commons.io.filefilter.IOFileFilter;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -15,14 +18,18 @@ import java.nio.file.Path;
|
|||
import java.nio.file.Paths;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
|
||||
public class LocalFileManager implements IFileManager {
|
||||
|
||||
@NonNls
|
||||
private static final String XML_DEPENDENCY_KEY = "dependencies.dependency";
|
||||
private HashSet<String> visitedScripts = new HashSet<>();
|
||||
protected HashSet<AbstractMossScript> executed = new HashSet<>();
|
||||
public static final LocalFileManager scriptsInstance;
|
||||
public static final int HASHING_BUFFER_SIZE = 8192;
|
||||
public static final int BYTE_CAST_MASK = 0xFF;
|
||||
@NonNls
|
||||
@SuppressWarnings("StaticCollection")
|
||||
private static HashMap<String, LocalFileManager> managers = new HashMap<>();
|
||||
|
||||
|
@ -34,7 +41,7 @@ public class LocalFileManager implements IFileManager {
|
|||
private HashMap<String, LocalFile> files = new HashMap<>();
|
||||
public static final IOFileFilter CVS_FILTER = FileFilterUtils.makeCVSAware(null);
|
||||
|
||||
public static LocalFileManager getFileManager(String key) {
|
||||
public static LocalFileManager getFileManager(@NonNls String key) {
|
||||
return managers.get(key);
|
||||
}
|
||||
|
||||
|
@ -43,16 +50,15 @@ public class LocalFileManager implements IFileManager {
|
|||
static Logger logger = Logger.getLogger(LocalFileManager.class);
|
||||
|
||||
@Override
|
||||
public LocalFile getFile(String name) throws IOException, FileNotFoundException {
|
||||
public LocalFile getFile(@NonNls String name) throws IOException, FileNotFoundException {
|
||||
String normalized = FilenameUtils.normalize(name);
|
||||
if (normalized == null) {
|
||||
logger.warn("Failed to normalize game resource filename: " + name);
|
||||
logger.warn(MessageFormat.format(Messages.getString("NORMALIZE_FAILED"), name));
|
||||
|
||||
throw new FileNotFoundException("The filename " + name
|
||||
+ " could not be normalized.");
|
||||
throw new FileNotFoundException(MessageFormat.format(Messages.getString("NORMALIZE_FAILED"), name));
|
||||
}
|
||||
File f = new File(this.basedir, normalized);
|
||||
logger.info("Got local file " + name + " as " + f.getAbsolutePath());
|
||||
logger.info(MessageFormat.format(Messages.getString("GOT_LOCAL_FILE"), name, f.getAbsolutePath()));
|
||||
|
||||
return new LocalFile(name, f);
|
||||
}
|
||||
|
@ -91,7 +97,7 @@ public class LocalFileManager implements IFileManager {
|
|||
NoSuchAlgorithmException, FileNotFoundException {
|
||||
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256"); //NON-NLS
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(f)) {
|
||||
try (FileChannel fc = fis.getChannel()) {
|
||||
|
@ -105,7 +111,6 @@ public class LocalFileManager implements IFileManager {
|
|||
bbf.flip();
|
||||
|
||||
|
||||
|
||||
md.update(bbf);
|
||||
|
||||
bbf.clear();
|
||||
|
@ -132,44 +137,33 @@ public class LocalFileManager implements IFileManager {
|
|||
return ImmutableList.copyOf(files.values());
|
||||
}
|
||||
|
||||
public IMossFile getScriptInitFile(String scName) throws IOException, FileNotFoundException {
|
||||
String normalized = FilenameUtils.normalize(scName);
|
||||
if (normalized == null) {
|
||||
logger.warn("Failed to normalize game resource filename: " + scName);
|
||||
|
||||
throw new FileNotFoundException("The filename " + scName
|
||||
+ " could not be normalized.");
|
||||
}
|
||||
final String scriptName = normalized + "/init.js";
|
||||
LocalFile scriptFile = getFile(scriptName);
|
||||
registerFile(scriptName, scriptFile);
|
||||
@Override
|
||||
public AbstractMossScript getScript(@NonNls final String name) throws IOException, MossWorldLoadException {
|
||||
@NonNls String normalized = FilenameUtils.normalize(name);
|
||||
try {
|
||||
final String indexName = normalized + "/index";
|
||||
@NonNls final String indexName = normalized + "/index";
|
||||
LocalFile fileIndex = getFile(indexName);
|
||||
registerFile(indexName, scriptFile);
|
||||
BufferedReader idxR = new BufferedReader(fileIndex.getReader());
|
||||
String line;
|
||||
@NonNls String line;
|
||||
while ((line = idxR.readLine()) != null) {
|
||||
String normalizedLine = FilenameUtils.normalize(line.trim());
|
||||
if (normalizedLine == null) {
|
||||
logger.warn("Failed to normalize game resource filename from file index: "
|
||||
+ line);
|
||||
logger.warn(MessageFormat.format(Messages.getString("INDEXED_NORMALIZE_FAILURE"), line));
|
||||
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
|
||||
final String filename = normalized + normalizedLine;
|
||||
@NonNls final String filename = normalized + normalizedLine;
|
||||
final LocalFile file = getFile(filename);
|
||||
this.registerFile(filename, file);
|
||||
} catch (FileNotFoundException e) {
|
||||
logger.warn("File was in index but not on disk: "
|
||||
+ line);
|
||||
logger.warn(MessageFormat.format(Messages.getString("INDEXED_NOT_ON_DISK"), name));
|
||||
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
logger.warn("No index file found; no files will be served to the client.");
|
||||
logger.warn(Messages.getString("NO_INDEX"));
|
||||
File base = new File(basedir, normalized);
|
||||
Path basePath = Paths.get(basedir.getAbsolutePath());
|
||||
for (File f : FileUtils.listFiles(base, CVS_FILTER, CVS_FILTER)) {
|
||||
|
@ -177,14 +171,82 @@ public class LocalFileManager implements IFileManager {
|
|||
Path path = Paths.get(f.getAbsolutePath());
|
||||
final String resolvedName = basePath.relativize(path).toFile().getPath();
|
||||
LocalFile file = this.getFile(resolvedName);
|
||||
logger.debug("Got file via recursive directory listing: " + resolvedName);
|
||||
logger.debug(MessageFormat.format(Messages.getString("FOUND_RECURSIVELY"), resolvedName));
|
||||
this.registerFile(resolvedName, file);
|
||||
} catch (FileNotFoundException fnfe2) {
|
||||
// should not happen
|
||||
logger.warn("Could not find file from recursive directory listing. This should never happen.");
|
||||
logger.warn(Messages.getString("RECURSIVE_LISTED_BUT_NOT_FOUND"));
|
||||
}
|
||||
}
|
||||
}
|
||||
List<AbstractMossScript> dependencies = new ArrayList<>();
|
||||
try {
|
||||
File scriptXml = new File(this.getFile(normalized + "/script.xml").getFilename());
|
||||
|
||||
|
||||
XMLConfiguration scriptCfg = new XMLConfiguration(scriptXml);
|
||||
String[] scNames = scriptCfg.getStringArray(XML_DEPENDENCY_KEY);
|
||||
for (@NonNls 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 LocalScript(name, dependencies);
|
||||
}
|
||||
|
||||
public IMossFile getScriptInitFile(String scName) throws IOException, FileNotFoundException {
|
||||
String normalized = FilenameUtils.normalize(scName);
|
||||
if (normalized == null) {
|
||||
logger.warn(MessageFormat.format(Messages.getString("FAILED_NORMALIZE_RSRC"), scName));
|
||||
|
||||
throw new FileNotFoundException(MessageFormat.format(Messages.getString("FAILED_NORMALIZE_RSRC"), scName));
|
||||
}
|
||||
@NonNls final String scriptName = normalized + "/init.js";
|
||||
LocalFile scriptFile = getFile(scriptName);
|
||||
registerFile(scriptName, scriptFile);
|
||||
|
||||
return scriptFile;
|
||||
}
|
||||
|
||||
private class LocalScript extends AbstractMossScript {
|
||||
|
||||
private final List<AbstractMossScript> dependencies;
|
||||
|
||||
public LocalScript(String name, List<AbstractMossScript> dependencies) {
|
||||
super(name);
|
||||
this.dependencies = dependencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exec(ScriptEnv sEnv) throws IOException, MossWorldLoadException {
|
||||
LocalFileManager.this.executed.add(this);
|
||||
for (AbstractMossScript sc : dependencies) {
|
||||
sc.exec(sEnv);
|
||||
}
|
||||
sEnv.runScript(this.getInitFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMossFile getInitFile() throws IOException {
|
||||
return LocalFileManager.this.getScriptInitFile(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AbstractMossScript> getDependencies() {
|
||||
return Collections.unmodifiableList(dependencies);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import net.mosstest.scripting.Player;
|
|||
import net.mosstest.scripting.Position;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
|
@ -35,9 +36,8 @@ public class LocalRenderPreparator implements IRenderPreparator {
|
|||
Position requested = LocalRenderPreparator.this.chunkRequests
|
||||
.take();
|
||||
System.out
|
||||
.println(Messages
|
||||
.getString("LocalRenderPreparator.MSG_REQUESTED") + requested.x + "," //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ requested.y + "," + requested.z); //$NON-NLS-1$
|
||||
.println(MessageFormat.format(Messages
|
||||
.getString("LocalRenderPreparator.MSG_REQUESTED"), requested.x, requested.y, requested.z)); //$NON-NLS-1$
|
||||
MapChunk chk = LocalRenderPreparator.this.nc
|
||||
.getChunk(requested);
|
||||
chk.pos = requested;
|
||||
|
@ -99,7 +99,7 @@ public class LocalRenderPreparator implements IRenderPreparator {
|
|||
InterruptedException {
|
||||
try {
|
||||
MapChunk chk = this.nc.getChunkFailFast(pos);
|
||||
logger.trace(chk == null ? "Chunk is null" : "Chunk obtained is: " + chk //$NON-NLS-1$
|
||||
logger.trace(chk == null ? "Chunk is null" : MessageFormat.format("Chunk obtained is {0}", chk) //$NON-NLS-1$
|
||||
.toString());
|
||||
if (chk == null) {
|
||||
this.chunkRequests.put(pos);
|
||||
|
|
|
@ -7,12 +7,14 @@ import net.mosstest.scripting.Position;
|
|||
import org.apache.log4j.Logger;
|
||||
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
|
||||
/**
|
||||
* The Class MapCache.
|
||||
*/
|
||||
|
@ -20,6 +22,7 @@ public class MapCache {
|
|||
private static final Logger logger = Logger.getLogger(MapCache.class);
|
||||
private final LoadingCache<Position, MapChunk> chunkCache;
|
||||
private final Map<Position, MapChunk> chunkCacheAsMap;
|
||||
|
||||
{
|
||||
chunkCache = CacheBuilder.newBuilder()
|
||||
.concurrencyLevel(4)
|
||||
|
@ -34,103 +37,103 @@ public class MapCache {
|
|||
/**
|
||||
* The db.
|
||||
*/
|
||||
private MapDatabase db ;
|
||||
|
||||
/**
|
||||
* Gets the chunk.
|
||||
*
|
||||
* @param pos the pos
|
||||
* @return the chunk
|
||||
* @throws MapGeneratorException the map generator exception
|
||||
*/
|
||||
public MapChunk getChunk(Position pos) throws MapGeneratorException {
|
||||
private MapDatabase db;
|
||||
|
||||
/**
|
||||
* Gets the chunk.
|
||||
*
|
||||
* @param pos the pos
|
||||
* @return the chunk
|
||||
* @throws MapGeneratorException the map generator exception
|
||||
*/
|
||||
public MapChunk getChunk(Position pos) throws MapGeneratorException {
|
||||
// we want loading implicitly (which will generate it)
|
||||
MapChunk chk = null;
|
||||
try {
|
||||
chk = chunkCache.get(pos);
|
||||
} catch (ExecutionException e) {
|
||||
logger.error("ExecutionException getting a chunk: "+e.getCause() + "/" + e.getMessage());
|
||||
logger.error(MessageFormat.format(Messages.getString("CHUNK_LDR_EXECUTION_EXCEPTION"), e.getMessage()));
|
||||
}
|
||||
if(chk == null){
|
||||
if (chk == null) {
|
||||
// loading from DB is still done if no chunk exists after an async load
|
||||
chk = db.getChunk(pos);
|
||||
// fill in, in case it was stored as compressed
|
||||
MapGenerators.getDefaultMapgen().fillInChunk(chk.getNodes(), pos);
|
||||
if(chk == null){
|
||||
if (chk == null) {
|
||||
// if still not loaded, generate
|
||||
chk = MapGenerators.getDefaultMapgen().generateChunk(pos);
|
||||
}
|
||||
}
|
||||
return chk;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the chunk fail fast.
|
||||
*
|
||||
* @param pos the pos
|
||||
* @return the chunk fail fast
|
||||
*/
|
||||
public MapChunk getChunkFailFast(Position pos) {
|
||||
// we don't want loading from DB or generating
|
||||
return chunkCacheAsMap.get(pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the chunk, updating cache and database.
|
||||
*
|
||||
* @param pos The position in question
|
||||
* Gets the chunk fail fast.
|
||||
*
|
||||
* @param pos the pos
|
||||
* @return the chunk fail fast
|
||||
*/
|
||||
public MapChunk getChunkFailFast(Position pos) {
|
||||
// we don't want loading from DB or generating
|
||||
return chunkCacheAsMap.get(pos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the chunk, updating cache and database.
|
||||
*
|
||||
* @param pos The position in question
|
||||
* @param chunk the chunk to be stored
|
||||
*/
|
||||
public void setChunk(Position pos, MapChunk chunk) {
|
||||
*/
|
||||
public void setChunk(Position pos, MapChunk chunk) {
|
||||
// plain and simple, we just store it
|
||||
chunk.compact();
|
||||
db.addMapChunk(pos, chunk);
|
||||
db.addMapChunk(pos, chunk);
|
||||
chunkCache.put(pos, chunk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new node cache.
|
||||
*
|
||||
* @param db the db
|
||||
*/
|
||||
public MapCache(MapDatabase db) {
|
||||
this.db = db;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chunk, or null if it is not generated.
|
||||
*
|
||||
* @param pos The position in question
|
||||
* @return the chunk, or null if it does not exist on disk.
|
||||
*/
|
||||
public MapChunk getChunkNoGenerate(Position pos) throws MapGeneratorException{
|
||||
/**
|
||||
* Instantiates a new node cache.
|
||||
*
|
||||
* @param db the db
|
||||
*/
|
||||
public MapCache(MapDatabase db) {
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chunk, or null if it is not generated.
|
||||
*
|
||||
* @param pos The position in question
|
||||
* @return the chunk, or null if it does not exist on disk.
|
||||
*/
|
||||
public MapChunk getChunkNoGenerate(Position pos) throws MapGeneratorException {
|
||||
// we don't want loading implicitly (which will generate it)
|
||||
MapChunk chk = chunkCacheAsMap.get(pos);
|
||||
if(chk == null){
|
||||
MapChunk chk = chunkCacheAsMap.get(pos);
|
||||
if (chk == null) {
|
||||
// loading from DB is still done
|
||||
chk = db.getChunk(pos);
|
||||
if(chk == null) return null; // not found in DB
|
||||
if (chk == null) return null; // not found in DB
|
||||
// fill in, in case it was stored as compressed. This still requires mapgen use as chunks are not guaranteed to be stored fully.
|
||||
MapGenerators.getDefaultMapgen().fillInChunk(chk.getNodes(), pos);
|
||||
}
|
||||
return chk;
|
||||
}
|
||||
}
|
||||
|
||||
private class RemovalListener implements com.google.common.cache.RemovalListener<Position, MapChunk> {
|
||||
|
||||
@Override
|
||||
public void onRemoval(RemovalNotification<Position, MapChunk> notification) {
|
||||
switch(notification.getCause()){
|
||||
switch (notification.getCause()) {
|
||||
case COLLECTED:
|
||||
logger.warn("Un-cacahing " + notification.getKey().toString() + " due to GC. Memory may be low.");
|
||||
logger.warn(MessageFormat.format(Messages.getString("GC_EVICT"), notification.getKey().toString()));
|
||||
break;
|
||||
case EXPIRED:
|
||||
logger.info("Un-cacahing " + notification.getKey().toString() + " as it expired");
|
||||
logger.info(MessageFormat.format(Messages.getString("UNCACHE_EXPIRE"), notification.getKey().toString()));
|
||||
case SIZE:
|
||||
logger.warn("Un-cacahing " + notification.getKey().toString() + " due to a size constraint");
|
||||
logger.warn(MessageFormat.format(Messages.getString("EVICT_SIZE"), notification.getKey().toString()));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -139,9 +142,9 @@ public class MapCache {
|
|||
private class PositionMapChunkCacheLoader extends CacheLoader<Position, MapChunk> {
|
||||
@Override
|
||||
public MapChunk load(Position position) throws Exception {
|
||||
logger.info("Re-loading " + position.toString() + " into cache.");
|
||||
logger.info(MessageFormat.format(Messages.getString("RELOADING_INTO_CACHE"), position.toString()));
|
||||
MapChunk chk = MapCache.this.db.getChunk(position);
|
||||
if(chk == null) {
|
||||
if (chk == null) {
|
||||
chk = MapGenerators.getDefaultMapgen().generateChunk(position);
|
||||
MapCache.this.db.addMapChunk(position, chk);
|
||||
}
|
||||
|
|
|
@ -8,12 +8,14 @@ import org.iq80.leveldb.Options;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import static org.fusesource.leveldbjni.JniDBFactory.factory;
|
||||
|
||||
//import static org.iq80.leveldb.impl.Iq80DBFactory.factory;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
|
||||
/**
|
||||
* The Class MapDatabase.
|
||||
*/
|
||||
|
@ -24,69 +26,81 @@ public class MapDatabase {
|
|||
*/
|
||||
DB map;
|
||||
|
||||
/** The entities. */
|
||||
DB entities;
|
||||
|
||||
/** The metadata. */
|
||||
DB metadata;
|
||||
|
||||
/** The map heavies. */
|
||||
DB mapHeavies;
|
||||
|
||||
/** The landclaims. */
|
||||
DB landclaims;
|
||||
|
||||
/** The players. */
|
||||
DB players;
|
||||
|
||||
/** The nodes. */
|
||||
public DB nodes;
|
||||
/**
|
||||
* The entities.
|
||||
*/
|
||||
DB entities;
|
||||
|
||||
/**
|
||||
* Instantiates a new map database.
|
||||
*
|
||||
* @param basedir the basedir
|
||||
* @throws MapDatabaseException the map database exception
|
||||
* @throws MossWorldLoadException the moss world load exception
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public MapDatabase(File basedir) throws MapDatabaseException,
|
||||
MossWorldLoadException {
|
||||
File dbDir = new File(basedir, "db"); //$NON-NLS-1$
|
||||
dbDir.mkdirs();
|
||||
try {
|
||||
/**
|
||||
* The metadata.
|
||||
*/
|
||||
DB metadata;
|
||||
|
||||
Options options = new Options();
|
||||
options.comparator(null);
|
||||
this.map = factory.open(new File(dbDir, "map"), options); //$NON-NLS-1$
|
||||
this.mapHeavies = factory.open(new File(dbDir, "mapHeavies"), //$NON-NLS-1$
|
||||
options);
|
||||
this.entities = factory.open(new File(dbDir, "entities"), options); //$NON-NLS-1$
|
||||
this.metadata = factory.open(new File(dbDir, "metadata"), options); //$NON-NLS-1$
|
||||
this.players = factory.open(new File(dbDir, "players"), options); //$NON-NLS-1$
|
||||
this.nodes = factory.open(new File(dbDir, "nodes"), options); //$NON-NLS-1$
|
||||
/**
|
||||
* The map heavies.
|
||||
*/
|
||||
DB mapHeavies;
|
||||
|
||||
/**
|
||||
* The landclaims.
|
||||
*/
|
||||
DB landclaims;
|
||||
|
||||
/**
|
||||
* The players.
|
||||
*/
|
||||
DB players;
|
||||
|
||||
/**
|
||||
* The nodes.
|
||||
*/
|
||||
public DB nodes;
|
||||
|
||||
/**
|
||||
* Instantiates a new map database.
|
||||
*
|
||||
* @param basedir the basedir
|
||||
* @throws MapDatabaseException the map database exception
|
||||
* @throws MossWorldLoadException the moss world load exception
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public MapDatabase(File basedir) throws MapDatabaseException,
|
||||
MossWorldLoadException {
|
||||
File dbDir = new File(basedir, "db"); //$NON-NLS-1$
|
||||
dbDir.mkdirs();
|
||||
try {
|
||||
|
||||
Options options = new Options();
|
||||
options.comparator(null);
|
||||
this.map = factory.open(new File(dbDir, "map"), options); //$NON-NLS-1$
|
||||
this.mapHeavies = factory.open(new File(dbDir, "mapHeavies"), //$NON-NLS-1$
|
||||
options);
|
||||
this.entities = factory.open(new File(dbDir, "entities"), options); //$NON-NLS-1$
|
||||
this.metadata = factory.open(new File(dbDir, "metadata"), options); //$NON-NLS-1$
|
||||
this.players = factory.open(new File(dbDir, "players"), options); //$NON-NLS-1$
|
||||
this.nodes = factory.open(new File(dbDir, "nodes"), options); //$NON-NLS-1$
|
||||
} catch (IOException e) {
|
||||
logger.error("IOException in database loading: " + e.toString());
|
||||
logger.error(MessageFormat.format(Messages.getString("DB_LOAD_IOEXCEPTION"), e.getMessage()));
|
||||
throw new MossWorldLoadException(Messages.getString("MapDatabase.ERR_DB_FAIL"), e); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
logger.info("Database loaded normally.");
|
||||
logger.info(Messages.getString("DB_NORMAL_LOAD"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Close.
|
||||
*
|
||||
* @throws MapDatabaseException the map database exception
|
||||
*/
|
||||
public void close() throws MapDatabaseException {
|
||||
/**
|
||||
* Close.
|
||||
*
|
||||
* @throws MapDatabaseException the map database exception
|
||||
*/
|
||||
public void close() throws MapDatabaseException {
|
||||
|
||||
logger.info("Database shutting down (normally)");
|
||||
try {
|
||||
this.map.close();
|
||||
this.entities.close();
|
||||
this.metadata.close();
|
||||
} catch (IOException e) {
|
||||
logger.info(Messages.getString("DB_SHUTDOWN_NORMAL"));
|
||||
try {
|
||||
this.map.close();
|
||||
this.entities.close();
|
||||
this.metadata.close();
|
||||
} catch (IOException e) {
|
||||
throw new MapDatabaseException("Database shutdown failed!", e,
|
||||
MapDatabaseException.SEVERITY_UNKNOWN
|
||||
| MapDatabaseException.SEVERITY_FATAL_TRANSIENT); //$NON-NLS-1$
|
||||
|
@ -103,39 +117,46 @@ public class MapDatabase {
|
|||
public MapChunk getChunk(final Position pos) throws MapGeneratorException {
|
||||
|
||||
byte[] chunk = this.map.get(pos.toBytes());
|
||||
if(chunk == null){
|
||||
if (chunk == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return new MapChunk(chunk);
|
||||
} catch (IOException e) {
|
||||
logger.error("IOException loading a chunk from byte[]");
|
||||
ExceptionHandler.registerException(e);
|
||||
return null;
|
||||
} catch (MosstestFatalDeathException e) {
|
||||
try {
|
||||
this.close();
|
||||
} catch (MapDatabaseException e1) {
|
||||
logger.error(MessageFormat.format(Messages.getString("DB_EMERGENCY_SHUTDOWN_FAIL"), e1.getMessage()));
|
||||
throw new MosstestFatalDeathException(e1);
|
||||
}
|
||||
logger.warn(Messages.getString("DB_SHUTDOWN_EMERGENCY"));
|
||||
|
||||
// MUST rethrow
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the map chunk.
|
||||
*
|
||||
* @param pos the pos
|
||||
* @param mapChunk the map chunk
|
||||
*/
|
||||
/**
|
||||
* Adds the map chunk.
|
||||
*
|
||||
* @param pos the pos
|
||||
* @param mapChunk the map chunk
|
||||
*/
|
||||
|
||||
void addMapChunk(Position pos, MapChunk mapChunk) {
|
||||
this.map.put(pos.toBytes(), mapChunk.writeLight(true));
|
||||
void addMapChunk(Position pos, MapChunk mapChunk) {
|
||||
this.map.put(pos.toBytes(), mapChunk.writeLight(true));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the heavy.
|
||||
*
|
||||
* @param pos the pos
|
||||
* @return the heavy
|
||||
*/
|
||||
public byte[] getHeavy(Position pos) {
|
||||
return this.mapHeavies.get(pos.toBytes());
|
||||
}
|
||||
/**
|
||||
* Gets the heavy.
|
||||
*
|
||||
* @param pos the pos
|
||||
* @return the heavy
|
||||
*/
|
||||
public byte[] getHeavy(Position pos) {
|
||||
return this.mapHeavies.get(pos.toBytes());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.mosstest.servercore;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
|
@ -21,8 +22,8 @@ public class Messages {
|
|||
*
|
||||
* @param identifier the identifier
|
||||
*/
|
||||
public static void changeLanguage(String identifier) {
|
||||
resBundle = ResourceBundle.getBundle(BUNDLE_NAME + "." + identifier);
|
||||
public static void changeLanguage(Locale identifier) {
|
||||
resBundle = ResourceBundle.getBundle(BUNDLE_NAME, identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package net.mosstest.servercore;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Properties;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
|
@ -40,7 +42,7 @@ public class MossDebugUtils {
|
|||
* @return the string
|
||||
*/
|
||||
public static String writeStracktrace(Exception e) {
|
||||
String fName = Integer.toString(System.identityHashCode(e), 16) + "@"
|
||||
@NonNls String fName = Integer.toString(System.identityHashCode(e), 16) + "@"
|
||||
+ System.currentTimeMillis();
|
||||
File write = new File("stacktraces/" + fName + ".txt");
|
||||
try {
|
||||
|
@ -51,7 +53,7 @@ public class MossDebugUtils {
|
|||
writer.close();
|
||||
}
|
||||
} catch (IOException e1) {
|
||||
logger.fatal(e1.getClass().getName() + " caught trying to write stacktrace of an existing exception. Message: " + e1.getMessage());
|
||||
logger.fatal(MessageFormat.format(Messages.getString("CAUGHT_EXCEPTION_WRITING_STACKTRACE"), e1.getClass().getName(), e1.getMessage()));
|
||||
}
|
||||
return write.getAbsolutePath();
|
||||
}
|
||||
|
@ -65,7 +67,7 @@ public class MossDebugUtils {
|
|||
public static String getDebugInformation(Exception e) {
|
||||
StringBuilder s = new StringBuilder(
|
||||
MossDebugUtils.getGitConfig("git.commit.id") + " on " + MossDebugUtils.getGitConfig("git.branch") + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
s.append(Messages.getString("MossDebugUtils.MSG_BUILT_ON")).append(MossDebugUtils.getGitConfig(Messages.getString("MossDebugUtils.27"))).append("\r\n\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
s.append(Messages.getString("MossDebugUtils.MSG_BUILT_ON")).append(MossDebugUtils.getGitConfig("git.build.time")).append("\r\n\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
s.append(Messages.getString("MossDebugUtils.MSG_EXCEPTION_CAUGHT")); //$NON-NLS-1$
|
||||
for (StackTraceElement ste : e.getStackTrace()) {
|
||||
s.append(ste.toString()).append("\r\n"); //$NON-NLS-1$
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.apache.commons.configuration.XMLConfiguration;
|
|||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -40,15 +41,14 @@ public class MossGame {
|
|||
Messages.getString("MossGame.CFG_LOAD_ERR")); //$NON-NLS-1$
|
||||
}
|
||||
this.scripts = new ArrayList<>();
|
||||
String[] scNames = this.gameCfg.getStringArray("plugin"); //$NON-NLS-1$
|
||||
String[] scNames = this.gameCfg.getStringArray("plugins.plugin"); //$NON-NLS-1$
|
||||
for (String scName : scNames)
|
||||
try {
|
||||
this.scripts.add(LocalFileManager.scriptsInstance
|
||||
.getScriptInitFile(scName)); //$NON-NLS-1$
|
||||
.getScript(scName)); //$NON-NLS-1$
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
throw new MossWorldLoadException(
|
||||
Messages.getString("MossGame.FILE_NOT_FOUND") + scName); //$NON-NLS-1$
|
||||
throw new MossWorldLoadException(MessageFormat.format(Messages.getString("MossGame.FILE_NOT_FOUND"), scName)); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,14 +66,14 @@ public class MossGame {
|
|||
private File cfgFile;
|
||||
|
||||
/** The scripts. */
|
||||
private ArrayList<IMossFile> scripts;
|
||||
private ArrayList<AbstractMossScript> scripts;
|
||||
|
||||
/**
|
||||
* Gets the scripts.
|
||||
*
|
||||
* @return the scripts
|
||||
*/
|
||||
public List<IMossFile> getScripts() {
|
||||
public List<AbstractMossScript> getScripts() {
|
||||
return ImmutableList.copyOf(this.scripts);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,36 +9,50 @@ import net.mosstest.servercore.MosstestSecurityManager.ThreadContext;
|
|||
import org.apache.commons.configuration.ConfigurationException;
|
||||
import org.apache.commons.configuration.XMLConfiguration;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class MossWorld {
|
||||
static {
|
||||
System.setSecurityManager(MosstestSecurityManager.instance);
|
||||
}
|
||||
static {
|
||||
System.setSecurityManager(MosstestSecurityManager.instance);
|
||||
}
|
||||
|
||||
static Logger logger = Logger.getLogger(MossWorld.class);
|
||||
private MossGame game;
|
||||
private File baseDir;
|
||||
private XMLConfiguration worldCfg;
|
||||
private File cfgFile;
|
||||
private MapDatabase db;
|
||||
private MapCache nc;
|
||||
private MossScriptEnv mossEnv;
|
||||
private ScriptEnv sEnv;
|
||||
private ScriptableDatabase sdb;
|
||||
private EventProcessor evp;
|
||||
static Logger logger = Logger.getLogger(MossWorld.class);
|
||||
private MossGame game;
|
||||
private File baseDir;
|
||||
private XMLConfiguration worldCfg;
|
||||
private File cfgFile;
|
||||
private MapDatabase db;
|
||||
private MapCache nc;
|
||||
private MossScriptEnv mossEnv;
|
||||
private ScriptEnv sEnv;
|
||||
private ScriptableDatabase sdb;
|
||||
private EventProcessor evp;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private ServerNetworkingManager snv;
|
||||
@SuppressWarnings("unused")
|
||||
private ServerNetworkingManager snv;
|
||||
|
||||
volatile boolean run = true;
|
||||
private FuturesProcessor fp;
|
||||
private INodeManager nm;
|
||||
private IRenderPreparator rp;
|
||||
private RenderProcessor rend;
|
||||
volatile boolean run = true;
|
||||
|
||||
public FuturesProcessor getFp() {
|
||||
return fp;
|
||||
}
|
||||
|
||||
public MossScriptEnv getMossEnv() {
|
||||
return mossEnv;
|
||||
}
|
||||
|
||||
public EventProcessor getEvp() {
|
||||
return evp;
|
||||
}
|
||||
|
||||
private FuturesProcessor fp;
|
||||
private INodeManager nm;
|
||||
private IRenderPreparator rp;
|
||||
private RenderProcessor rend;
|
||||
private ItemManager im;
|
||||
|
||||
/**
|
||||
|
@ -46,96 +60,98 @@ public class MossWorld {
|
|||
* initialized, loaded, and passes basic consistency checks. This
|
||||
* constructor will not initialize load-balancing.
|
||||
*
|
||||
* @param name
|
||||
* A string that names the world.
|
||||
* @param port
|
||||
* The port number on which to run the server. If negative a
|
||||
* singleplayer stack is created.
|
||||
* @throws MossWorldLoadException
|
||||
* Thrown if the world cannot be loaded, due to inconsistency,
|
||||
* missing files, or lack of system resources.
|
||||
* @param name A string that names the world.
|
||||
* @param port The port number on which to run the server. If negative a
|
||||
* singleplayer stack is created.
|
||||
* @throws MossWorldLoadException Thrown if the world cannot be loaded, due to inconsistency,
|
||||
* missing files, or lack of system resources.
|
||||
* @throws MapDatabaseException
|
||||
* @throws IOException
|
||||
* @throws ConfigurationException
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public MossWorld(String name, int port) throws MossWorldLoadException,
|
||||
MapDatabaseException, IOException, ConfigurationException {
|
||||
//Thread.currentThread().setContextClassLoader(
|
||||
// MosstestSecurityManager.instance.getScriptClassLoader(Thread
|
||||
// .currentThread().getContextClassLoader()));
|
||||
this.baseDir = new File("data/worlds/" + name); //$NON-NLS-1$
|
||||
if (!this.baseDir.exists()) {
|
||||
this.baseDir.mkdirs();
|
||||
@SuppressWarnings("nls")
|
||||
public MossWorld(@NonNls String name, int port) throws MossWorldLoadException,
|
||||
MapDatabaseException, IOException {
|
||||
//Thread.currentThread().setContextClassLoader(
|
||||
// MosstestSecurityManager.instance.getScriptClassLoader(Thread
|
||||
// .currentThread().getContextClassLoader()));
|
||||
this.baseDir = new File("data/worlds/" + name); //$NON-NLS-1$
|
||||
if (!this.baseDir.exists()) {
|
||||
this.baseDir.mkdirs();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the security manager to trust attempts to open anything below
|
||||
// data/scripts
|
||||
MosstestSecurityManager.instance
|
||||
.setTrustedBasedir(new File("scripts/"));
|
||||
this.cfgFile = new File(this.baseDir, "world.xml"); //$NON-NLS-1$
|
||||
if (!this.cfgFile.isFile())
|
||||
// Sets the security manager to trust attempts to open anything below
|
||||
// data/scripts
|
||||
MosstestSecurityManager.instance
|
||||
.setTrustedBasedir(new File("scripts/"));
|
||||
this.cfgFile = new File(this.baseDir, "world.xml"); //$NON-NLS-1$
|
||||
if (!this.cfgFile.isFile())
|
||||
|
||||
this.cfgFile.createNewFile();
|
||||
this.worldCfg = new XMLConfiguration(this.cfgFile);
|
||||
this.cfgFile.createNewFile();
|
||||
try {
|
||||
this.worldCfg = new XMLConfiguration(this.cfgFile);
|
||||
} catch (ConfigurationException e) {
|
||||
logger.fatal(Messages.getString("GAME_CFG_DATA_GONE"));
|
||||
}
|
||||
if (!this.worldCfg.containsKey("gameid")) { //$NON-NLS-1$
|
||||
throw new MossWorldLoadException(
|
||||
Messages.getString("MossWorld.NO_GAME_ID")); //$NON-NLS-1$
|
||||
}
|
||||
this.game = new MossGame(this.worldCfg.getString("gameid")); //$NON-NLS-1$
|
||||
|
||||
if (!this.worldCfg.containsKey("gameid")) { //$NON-NLS-1$
|
||||
throw new MossWorldLoadException(
|
||||
Messages.getString("MossWorld.NO_GAME_ID")); //$NON-NLS-1$
|
||||
}
|
||||
this.game = new MossGame(this.worldCfg.getString("gameid")); //$NON-NLS-1$
|
||||
try {
|
||||
this.db = new MapDatabase(this.baseDir);
|
||||
} catch (MapDatabaseException e) {
|
||||
throw new MossWorldLoadException(
|
||||
Messages.getString("MossWorld.ERR_DB")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
try {
|
||||
this.db = new MapDatabase(this.baseDir);
|
||||
} catch (MapDatabaseException e) {
|
||||
throw new MossWorldLoadException(
|
||||
Messages.getString("MossWorld.ERR_DB")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
this.nc = new MapCache(this.db);
|
||||
this.nc = new MapCache(this.db);
|
||||
this.im = new ItemManager();
|
||||
this.nm = new LocalNodeManager(this.db.nodes, im);
|
||||
// this.db = new MapDatabase(this.baseDir);
|
||||
try {
|
||||
MapGenerators.setDefaultMapGenerator(
|
||||
try {
|
||||
MapGenerators.setDefaultMapGenerator(
|
||||
new SimplexMapGenerator(), this.nm, 8448);
|
||||
} catch (MapGeneratorException e) {
|
||||
System.err.println(Messages
|
||||
.getString("MossWorld.MG_SELECT_FAILURE")); //$NON-NLS-1$
|
||||
System.exit(4);
|
||||
}
|
||||
this.sdb = new ScriptableDatabase(this.baseDir);
|
||||
this.fp = new FuturesProcessor(0);
|
||||
this.mossEnv = new MossScriptEnv(this.sdb, this.nc, this.fp, this.nm);
|
||||
this.sEnv = new ScriptEnv(this.mossEnv);
|
||||
List<IMossFile> scripts = this.game.getScripts();
|
||||
for (IMossFile sc : scripts) {
|
||||
this.sEnv.runScript(sc);
|
||||
}
|
||||
this.evp = new EventProcessor(this.mossEnv,
|
||||
ThreadContext.CONTEXT_SCRIPT);
|
||||
if (port >= 0) {
|
||||
logger.error(Messages.getString("MossWorld.NO_NETWORKING_NOW")); //$NON-NLS-1$
|
||||
/*
|
||||
.getString("MossWorld.MG_SELECT_FAILURE")); //$NON-NLS-1$
|
||||
System.exit(4);
|
||||
}
|
||||
this.sdb = new ScriptableDatabase(this.baseDir);
|
||||
this.fp = new FuturesProcessor(0);
|
||||
this.mossEnv = new MossScriptEnv(this.sdb, this.nc, this.fp, this.nm);
|
||||
this.sEnv = new ScriptEnv(this.mossEnv);
|
||||
List<AbstractMossScript> scripts = this.game.getScripts();
|
||||
for (AbstractMossScript sc : scripts) {
|
||||
sc.exec(sEnv);
|
||||
}
|
||||
this.evp = new EventProcessor(this.mossEnv,
|
||||
ThreadContext.CONTEXT_SCRIPT);
|
||||
if (port >= 0) {
|
||||
logger.error(Messages.getString("MossWorld.NO_NETWORKING_NOW")); //$NON-NLS-1$
|
||||
/*
|
||||
* try { this.snv = new ServerNetworkingManager(port, this); } catch
|
||||
* (IOException e) { throw new MossWorldLoadException(
|
||||
* "Failure in opening server socket for listening!"); }
|
||||
*/
|
||||
} // else {
|
||||
/* */this.rp = new LocalRenderPreparator(this.rend, this.nc);
|
||||
this.rp.setNodeManager(nm);
|
||||
/* */this.rend = RenderProcessor.init(this.nm, this.rp);
|
||||
// }
|
||||
} // else {
|
||||
/* */
|
||||
this.rp = new LocalRenderPreparator(this.rend, this.nc);
|
||||
this.rp.setNodeManager(nm);
|
||||
/* */
|
||||
this.rend = RenderProcessor.init(this.nm, this.rp);
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void enqueueEvent(IMossEvent e) throws InterruptedException {
|
||||
this.evp.eventQueue.put(e);
|
||||
}
|
||||
public void enqueueEvent(IMossEvent e) throws InterruptedException {
|
||||
this.evp.eventQueue.put(e);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws MossWorldLoadException,
|
||||
MapDatabaseException, ConfigurationException, IOException {
|
||||
public static void main(String[] args) throws MossWorldLoadException,
|
||||
MapDatabaseException, ConfigurationException, IOException {
|
||||
new MossWorld("test", -1); //$NON-NLS-1$
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +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);
|
||||
}
|
||||
}
|
|
@ -5,9 +5,12 @@ import org.apache.log4j.Logger;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FilePermission;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.security.AccessController;
|
||||
import java.security.Permission;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
|
||||
|
@ -25,16 +28,35 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
* The logger.
|
||||
*/
|
||||
static Logger logger = Logger.getLogger(MosstestSecurityManager.class);
|
||||
private final boolean testMode;
|
||||
|
||||
public MosstestSecurityManager(boolean testMode) {
|
||||
this.testMode = testMode;
|
||||
if (testMode) logger.warn(Messages.getString("SECURITY_MANAGER_TESTMODE"));
|
||||
File classDir = null;
|
||||
try {
|
||||
classDir = new File(MossScriptEnv.class.getProtectionDomain()
|
||||
.getCodeSource().getLocation().getPath()) // net.mosstest.scripting.MossScriptEnv
|
||||
.getParentFile() // net.mosstest.scripting
|
||||
.getCanonicalFile();
|
||||
} catch (IOException e) {
|
||||
logger.warn(Messages.getString("NO_CLASSDIR"));
|
||||
} finally {
|
||||
this.classDirectory = classDir;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void checkPermission(Permission perm) {
|
||||
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
logger.fatal("Requested permssion " + perm);
|
||||
logger.warn("MosstestSecurityManager prevented the use of arbitrary permissions outside engine contexts.");
|
||||
logger.fatal(MessageFormat.format(Messages.getString("PERMISSION_REQUESTED"), perm));
|
||||
if (testMode && perm.getName().equals("setIO")) return; //NON-NLS
|
||||
logger.warn(Messages.getString("ARBITRARY_PERMISSIONS"));
|
||||
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager prevented the use of arbitrary permissions outside engine contexts.");
|
||||
Messages.getString("ARBITRARY_PERMISSIONS"));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +69,6 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
*/
|
||||
@Override
|
||||
public void checkPermission(Permission perm, Object context) {
|
||||
System.err.println(perm.toString() + ":" + context.toString());
|
||||
checkPermission(perm);
|
||||
}
|
||||
|
||||
|
@ -69,17 +90,17 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
* The lock.
|
||||
*/
|
||||
private InheritableThreadLocal<Object> lock = new InheritableThreadLocal<>();
|
||||
private File basedir;
|
||||
private File baseDirectory;
|
||||
// Class dir corresponding to "net.mosstest"
|
||||
private final File classDir;
|
||||
private final File classDirectory;
|
||||
|
||||
public void setTrustedBasedir(File basedir) throws SecurityException,
|
||||
IOException {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
logger.error("The security manager prevented an attempt to set the trusted basedir.");
|
||||
throw new SecurityException("Cannot set basedir.");
|
||||
logger.error(Messages.getString("SECURITY_TRUSTED_BASEDIR"));
|
||||
throw new SecurityException(Messages.getString("NO_SET_BASEDIR"));
|
||||
}
|
||||
this.basedir = basedir.getCanonicalFile();
|
||||
this.baseDirectory = basedir.getCanonicalFile();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,9 +112,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void lock(Object key, ThreadContext tc) {
|
||||
if ((this.lock.get() != null)
|
||||
|| this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
logger.error("The security manager prevented an attempt to lock it on an already-locked thread.");
|
||||
logger.error(Messages.getString("THREAD_LOCKED"));
|
||||
throw new SecurityException(
|
||||
"The security manager is already locked for this thread.");
|
||||
Messages.getString("ALREADY_LOCKED"));
|
||||
}
|
||||
this.lock.set(key);
|
||||
this.threadContext.set(tc);
|
||||
|
@ -102,6 +123,7 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
|
||||
private Object forceUnlock() {
|
||||
Object key = this.lock.get();
|
||||
this.lock.set(null);
|
||||
this.threadContext.set(ThreadContext.CONTEXT_ENGINE);
|
||||
return key;
|
||||
}
|
||||
|
@ -113,9 +135,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
*/
|
||||
public void unlock(Object key) {
|
||||
if (this.lock.get() != key) {
|
||||
logger.error("The security manager prevented an attempt to unlock it using a mismatched key.");
|
||||
logger.error(Messages.getString("SECURITY_MISMATCHED_KEY"));
|
||||
throw new SecurityException(
|
||||
"A mismatched key has been used to unlock this thread.");
|
||||
Messages.getString("SECURITY_BAD_KEY"));
|
||||
}
|
||||
this.threadContext.set(ThreadContext.CONTEXT_ENGINE);
|
||||
}
|
||||
|
@ -127,7 +149,7 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
*/
|
||||
public void setConnectedPeer(String connectedPeer) {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
logger.warn("MosstestSecurityManager prevented a non-engine-context thread from changing the connected peer.");
|
||||
logger.warn(Messages.getString("SECURITY_PEER_CHANGE"));
|
||||
throw new SecurityException(
|
||||
"Attempted to set the connected peer from outside engine code");
|
||||
}
|
||||
|
@ -151,7 +173,7 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
*/
|
||||
public void setThreadContext(ThreadContext tc) {
|
||||
if (this.threadContext.get() == null) {
|
||||
logger.warn("A thread has started without inheriting a thread context and has been elevated");
|
||||
logger.warn(Messages.getString("THREAD_ELEVATED"));
|
||||
this.threadContext.set(tc);
|
||||
|
||||
return;
|
||||
|
@ -161,9 +183,8 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
this.threadContext.set(tc);
|
||||
}
|
||||
if (old != ThreadContext.CONTEXT_ENGINE) {
|
||||
logger.warn("Attempted to set the thread context type from non-engine code");
|
||||
throw new SecurityException(
|
||||
"Attempted to set the thread context type from non-engine code");
|
||||
logger.warn(Messages.getString("THREAD_CONTEXT_NON_ENGINE_CODE"));
|
||||
throw new SecurityException(Messages.getString("THREAD_CONTEXT_NON_ENGINE_CODE"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +222,7 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
private InheritableThreadLocal<ThreadContext> threadContext = new InheritableThreadLocal<MosstestSecurityManager.ThreadContext>() {
|
||||
@Override
|
||||
protected ThreadContext initialValue() {
|
||||
logger.warn("A thread has started without inheriting a thread context and has been elevated");
|
||||
logger.warn(Messages.getString("THREAD_ELEVATED"));
|
||||
return ThreadContext.CONTEXT_ENGINE;
|
||||
}
|
||||
};
|
||||
|
@ -220,9 +241,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkCreateClassLoader() {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to create a classloader");
|
||||
logger.warn(Messages.getString("SECURITY_CLASSLOADER"));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to create a classloader");
|
||||
Messages.getString("SECURITY_CLASSLOADER"));
|
||||
|
||||
} else {
|
||||
super.checkCreateClassLoader();
|
||||
|
@ -237,11 +258,12 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
*/
|
||||
@Override
|
||||
public void checkAccess(Thread t) {
|
||||
if (testMode) return;
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to stop or modify a thread");
|
||||
logger.warn(Messages.getString("SECURITY_THREAD"));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to stop or modify a thread");
|
||||
Messages.getString("SECURITY_THREAD"));
|
||||
|
||||
} else {
|
||||
}
|
||||
|
@ -254,11 +276,12 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
*/
|
||||
@Override
|
||||
public void checkAccess(ThreadGroup g) {
|
||||
if (testMode) return;
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to modify a ThreadGroup");
|
||||
logger.warn(Messages.getString("SECURITY_THREADGROUP"));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to modify a ThreadGroup");
|
||||
Messages.getString("SECURITY_THREADGROUP"));
|
||||
|
||||
} else {
|
||||
}
|
||||
|
@ -271,11 +294,12 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
*/
|
||||
@Override
|
||||
public void checkExit(int status) {
|
||||
if (testMode) return;
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to exit Mosstest improperly from a script");
|
||||
logger.warn(Messages.getString("SECURITY_EXIT"));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to exit Mosstest improperly from a script");
|
||||
Messages.getString("SECURITY_EXIT"));
|
||||
|
||||
}
|
||||
super.checkExit(status);
|
||||
|
@ -290,9 +314,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
@Override
|
||||
public void checkExec(String cmd) {
|
||||
|
||||
logger.warn("MosstestSecurityManager does not allow any script or portion of the engine to start a new process");
|
||||
logger.warn(Messages.getString("SECURITY_SPAWN_PROC"));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager does not allow any script or portion of the engine to start a new process");
|
||||
Messages.getString("SECURITY_SPAWN_PROC"));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -304,9 +328,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkLink(String lib) {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to link to a JN library from insecure code");
|
||||
logger.warn(Messages.getString("SECURITY_LINK"));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to link to a JN library from insecure code");
|
||||
Messages.getString("SECURITY_LINK"));
|
||||
|
||||
}
|
||||
|
||||
|
@ -321,10 +345,11 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkRead(FileDescriptor fd) {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("1MosstestSecurityManager stopped an attempt to read a file from non-core code "
|
||||
+ fd.toString());
|
||||
logger.warn(MessageFormat.format(Messages.getString("SECURITY_READFILE")
|
||||
, fd.toString()));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to read a file from non-core code");
|
||||
MessageFormat.format(Messages.getString("SECURITY_READFILE"), fd.toString())
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -338,32 +363,39 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkRead(String file) {
|
||||
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
// List<File> safeDirectories = Arrays.asList(this.baseDirectory, this.classDirectory);
|
||||
ThreadContext oldTc = MosstestSecurityManager.this
|
||||
.getThreadContext();
|
||||
Object oldLock = MosstestSecurityManager.this.forceUnlock();
|
||||
File tested;
|
||||
// try {
|
||||
//
|
||||
//
|
||||
// tested = new File(file).getCanonicalFile();
|
||||
// //MosstestSecurityManager.this.lock(oldLock, oldTc);
|
||||
// } catch (IOException e1) {
|
||||
// throw new SecurityException("The base directory failed to resolve!", e1);
|
||||
// }
|
||||
//
|
||||
// do {
|
||||
// if (safeDirectories.contains(file)) {
|
||||
// MosstestSecurityManager.this.lock(oldLock, oldTc);
|
||||
// return;
|
||||
// }
|
||||
// tested = tested.getParentFile();
|
||||
// } while (tested != null);
|
||||
try {
|
||||
ThreadContext oldTc = MosstestSecurityManager.this
|
||||
.getThreadContext();
|
||||
Object oldLock = MosstestSecurityManager.this.forceUnlock();
|
||||
|
||||
tested = new File(file).getCanonicalFile();
|
||||
MosstestSecurityManager.this.lock(oldLock, oldTc);
|
||||
} catch (IOException e1) {
|
||||
throw new SecurityException(
|
||||
"The basedir resolution failed to resolve!");
|
||||
AccessController.checkPermission(new FilePermission(file, "read")); //NON-NLS
|
||||
} catch (SecurityException e) {
|
||||
// lock
|
||||
this.lock(oldLock, oldTc);
|
||||
// rethrow to bail to a failure
|
||||
throw e;
|
||||
}
|
||||
|
||||
File parentFile = tested;
|
||||
while (parentFile != null) {
|
||||
if (basedir.equals(parentFile) || classDir.equals(parentFile)) {
|
||||
return;
|
||||
}
|
||||
parentFile = parentFile.getParentFile();
|
||||
}
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to read a file from non-core code"
|
||||
+ file);
|
||||
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to read a file from non-core code");
|
||||
super.checkRead(file);
|
||||
|
||||
this.lock(oldLock, oldTc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,10 +409,12 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkRead(String file, Object context) {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("3MosstestSecurityManager stopped an attempt to read a file from non-core code: "
|
||||
+ file);
|
||||
logger.warn(MessageFormat.format(Messages.getString("SECURITY_READ")
|
||||
, file));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to read a file from non-core code");
|
||||
MessageFormat.format(Messages.getString("SECURITY_READ")
|
||||
, file)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -394,9 +428,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkWrite(FileDescriptor fd) {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to write to a file from non-core code");
|
||||
logger.warn(Messages.getString("SECURITY_WRITE"));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to write to a file from non-core code");
|
||||
Messages.getString("SECURITY_WRITE"));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -410,9 +444,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkWrite(String file) {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to write to a file from non-core code");
|
||||
logger.warn(Messages.getString("SECURITY_WRITE"));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to write to a file from non-core code");
|
||||
Messages.getString("SECURITY_WRITE"));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -426,7 +460,7 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkDelete(String file) {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to delete a file from non-core code");
|
||||
logger.warn(Messages.getString("SECURITY_DELETE"));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to delete a file from non-core code");
|
||||
|
||||
|
@ -441,11 +475,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
@Override
|
||||
public void checkConnect(String host, int port) {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
if ((port != PORT_HTTP && port != PORT_HTTPS) && (port > MIN_SCRIPT_PORT || port < MAX_SCRIPT_PORT))
|
||||
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to connect to a network port other than 80, 443, or any port in the range 16512-16600");
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to connect to a network port other than 80, 443, or any port in the range 16512-16600");
|
||||
logger.warn(Messages.getString("SECURITY_CONNECT"));
|
||||
throw new SecurityException(Messages.getString("SECURITY_CONNECT"));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -459,22 +491,11 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
@Override
|
||||
public void checkConnect(String host, int port, Object context) {
|
||||
if (this.threadContext.get() == ThreadContext.CONTEXT_CLIENT) {
|
||||
if ((port != PORT_HTTP && port != PORT_HTTPS) && (port > MIN_SCRIPT_PORT || port < MAX_SCRIPT_PORT)) {
|
||||
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to connect to a network port other than 80, 443, or any port in the range 16512-16600");
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to connect to a network port other than 80, 443, or any port in the range 16512-16600");
|
||||
}
|
||||
if (!host.equals(this.connectedPeer)) {
|
||||
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt for the client to connect to a peer other than the server currently played");
|
||||
}
|
||||
} else if (this.threadContext.get() == ThreadContext.CONTEXT_LOCKDOWN) {
|
||||
|
||||
logger.warn("MosstestSecurityManager has denied a thread in lockdown to open a network connection");
|
||||
logger.warn(Messages.getString("SECURITY_LISTEN"));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager has denied a thread in lockdown to open a network connection");
|
||||
"MosstestSecurityManager stopped an attempt to listen directly on a network port.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -486,18 +507,11 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
@Override
|
||||
public void checkListen(int port) {
|
||||
if (this.threadContext.get() == ThreadContext.CONTEXT_SCRIPT) {
|
||||
if ((port > MIN_SCRIPT_PORT || port < MAX_SCRIPT_PORT))
|
||||
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to listen on a port not in the range 16512-16600");
|
||||
|
||||
logger.warn(Messages.getString("SECURITY_LISTEN"));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to listen on a port not in the range 16512-16600");
|
||||
|
||||
} else if (this.threadContext.get() == ThreadContext.CONTEXT_LOCKDOWN
|
||||
|| this.threadContext.get() == ThreadContext.CONTEXT_CLIENT) {
|
||||
|
||||
logger.warn("MosstestSecurityManager has denied a thread in lockdown or running a client script to listen on a port");
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager has denied a thread in lockdown or running a client script to listen on a port");
|
||||
Messages.getString("SECURITY_LISTEN"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -509,18 +523,10 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
@Override
|
||||
public void checkAccept(String host, int port) {
|
||||
if (this.threadContext.get() == ThreadContext.CONTEXT_SCRIPT) {
|
||||
if ((port > MIN_SCRIPT_PORT || port < MAX_SCRIPT_PORT))
|
||||
|
||||
logger.warn("MosstestSecurityManager stopped an attempt to listen on a port not in the range 16512-16600");
|
||||
logger.warn(Messages.getString("SECURITY_LISTEN"));
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager stopped an attempt to listen on a port not in the range 16512-16600");
|
||||
|
||||
} else if (this.threadContext.get() == ThreadContext.CONTEXT_LOCKDOWN
|
||||
|| this.threadContext.get() == ThreadContext.CONTEXT_CLIENT) {
|
||||
|
||||
logger.warn("MosstestSecurityManager has denied a thread in lockdown or running a client script to listen on a port");
|
||||
throw new SecurityException(
|
||||
"MosstestSecurityManager has denied a thread in lockdown or running a client script to listen on a port");
|
||||
Messages.getString("SECURITY_LISTEN"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -533,9 +539,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkMulticast(InetAddress maddr) {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager has denied a script use of multicast directly without use of loadbalancing facilities");
|
||||
logger.warn(Messages.getString("MULTICAST"));
|
||||
throw new SecurityException(
|
||||
"Scripts may not use mutlicast under any circumstances, except through the engine loadbalancing facilities");
|
||||
Messages.getString("MULTICAST2"));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -549,9 +555,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkMulticast(InetAddress maddr, byte ttl) {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager has denied a script use of multicast directly without use of loadbalancing facilities");
|
||||
logger.warn(Messages.getString("MULTICAST"));
|
||||
throw new SecurityException(
|
||||
"Scripts may not use mutlicast under any circumstances, except through the engine loadbalancing facilities");
|
||||
Messages.getString("MULTICAST2"));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -563,11 +569,12 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
*/
|
||||
@Override
|
||||
public void checkPropertiesAccess() {
|
||||
if (testMode) return;
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager has denied a thread running outside the engine context the right to access system properties.");
|
||||
logger.warn(Messages.getString("SYS_PROPERTIES"));
|
||||
throw new SecurityException(
|
||||
"Scripts may not access system properties");
|
||||
Messages.getString("SYS_PROPERTIES_SHORT"));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -579,11 +586,12 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
*/
|
||||
@Override
|
||||
public void checkPropertyAccess(String key) {
|
||||
if (testMode) return;
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager has denied a thread running outside the engine context the right to access system properties.");
|
||||
logger.warn(Messages.getString("SYS_PROPERTIES"));
|
||||
throw new SecurityException(
|
||||
"Scripts may not access system properties");
|
||||
MessageFormat.format(Messages.getString("SYS_PROPERTIES_SHORT_NAMED"), key));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -597,9 +605,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public boolean checkTopLevelWindow(Object window) {
|
||||
if (this.threadContext.get() == ThreadContext.CONTEXT_LOCKDOWN) {
|
||||
|
||||
logger.warn("MosstestSecurityManager has blocked a thread running outside the engine context frop opening a top-level window.");
|
||||
logger.warn(Messages.getString("TOP_LEVEL"));
|
||||
throw new SecurityException(
|
||||
"Threads in lockdown may not create top-level windows");
|
||||
Messages.getString("TOP_LEVEL_SHORT"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -612,9 +620,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
@Override
|
||||
public void checkPrintJobAccess() {
|
||||
|
||||
logger.warn("MosstestSecurityManager has denied a thread running outside the engine context the right to access system print jobs.");
|
||||
logger.warn(Messages.getString("PRINT"));
|
||||
throw new SecurityException(
|
||||
"Print job access is not allowed for the engine or scripts");
|
||||
Messages.getString("PRINT_SHORT"));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -626,9 +634,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkSystemClipboardAccess() {
|
||||
if (this.threadContext.get() == ThreadContext.CONTEXT_LOCKDOWN) {
|
||||
|
||||
logger.warn("MosstestSecurityManager has prevented a thread in lockdown from accessing the system clipboard.");
|
||||
logger.warn(Messages.getString("CLIPBOARD"));
|
||||
throw new SecurityException(
|
||||
"Threads in lockdown may not access the system clipboard");
|
||||
Messages.getString("CLIPBOARD_SHORT"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -641,9 +649,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkAwtEventQueueAccess() {
|
||||
if (this.threadContext.get() == ThreadContext.CONTEXT_LOCKDOWN) {
|
||||
|
||||
logger.warn("MosstestSecurityManager has prevented a thread in lockdown from accessing the AWT queue.");
|
||||
logger.warn(Messages.getString("AWT_QUEUE"));
|
||||
throw new SecurityException(
|
||||
"Threads in lockdown may not access the AWT queue");
|
||||
Messages.getString("AWT_QUEUE_SHORT"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -676,9 +684,9 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkSetFactory() {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager has prevented a thread in lockdown from setting a Java system factory.");
|
||||
logger.warn(Messages.getString("SYS_FACTORY"));
|
||||
throw new SecurityException(
|
||||
"Non-engine threads may not set java system factories");
|
||||
Messages.getString("SYS_FACTORY_SHORT"));
|
||||
}
|
||||
super.checkSetFactory();
|
||||
}
|
||||
|
@ -719,26 +727,15 @@ public class MosstestSecurityManager extends SecurityManager {
|
|||
public void checkMosstestControl() {
|
||||
if (this.threadContext.get() != ThreadContext.CONTEXT_ENGINE) {
|
||||
|
||||
logger.warn("MosstestSecurityManager has prevented a plugin from controlling certain portions of the Mosstest engine.");
|
||||
logger.warn(Messages.getString("PLUGIN_CTRL"));
|
||||
throw new SecurityException(
|
||||
"Non-engine threads may not set java system factories");
|
||||
Messages.getString("CTRL_SHORT"));
|
||||
}
|
||||
super.checkSetFactory();
|
||||
}
|
||||
|
||||
public MosstestSecurityManager() {
|
||||
File classDir = null;
|
||||
try {
|
||||
classDir = new File(MossScriptEnv.class.getProtectionDomain()
|
||||
.getCodeSource().getLocation().getPath()) // net.mosstest.scripting.MossScriptEnv
|
||||
.getParentFile() // net.mosstest.scripting
|
||||
.getParentFile() // net.mosstest
|
||||
.getCanonicalFile();
|
||||
} catch (IOException e) {
|
||||
logger.warn("Failed to obtain a class directory for the security manager, surious classloading failures may result.");
|
||||
} finally {
|
||||
this.classDir = classDir;
|
||||
}
|
||||
this(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.nio.IntBuffer;
|
|||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.jme3.material.RenderState;
|
||||
import jme3tools.optimize.GeometryBatchFactory;
|
||||
import net.mosstest.scripting.MapChunk;
|
||||
import net.mosstest.scripting.Player;
|
||||
|
@ -183,9 +184,13 @@ public class RenderProcessor extends SimpleApplication {
|
|||
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/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;
|
||||
}
|
||||
|
@ -364,4 +369,4 @@ public class RenderProcessor extends SimpleApplication {
|
|||
inputManager.addListener(rotationListener, "CAM_Down");
|
||||
inputManager.addListener(activityListener, "TestFeature");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,18 +6,19 @@ import org.apache.log4j.Logger;
|
|||
import org.mozilla.javascript.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
|
||||
/**
|
||||
* Static environment for executing scripts. Call {@link ScriptEnv#runScript()}
|
||||
* Static environment for executing scripts. Call {@link ScriptEnv#runScript(IMossFile)}
|
||||
* to call a script.
|
||||
*
|
||||
* @author rarkenin
|
||||
*/
|
||||
public class ScriptEnv {
|
||||
|
||||
static Logger logger = Logger.getLogger(MossDebugUtils.class);
|
||||
static Logger logger = Logger.getLogger(ScriptEnv.class);
|
||||
|
||||
ImporterTopLevel globalScope;
|
||||
|
||||
|
@ -71,19 +72,18 @@ public class ScriptEnv {
|
|||
Object lock = new Object();
|
||||
MosstestSecurityManager.instance.lock(lock,
|
||||
ThreadContext.CONTEXT_SCRIPT);
|
||||
|
||||
sc.exec(this.cx, this.globalScope);
|
||||
|
||||
MosstestSecurityManager.instance.unlock(lock);
|
||||
} catch (IOException e) {
|
||||
logger.fatal(MessageFormat.format(Messages.getString("SCRIPT_IOEXCEPTION"), script.getName(), e.getLocalizedMessage()));
|
||||
return ScriptResult.RESULT_ERROR;
|
||||
} catch (RhinoException e) {
|
||||
logger.error("A script error has occured: " + e.getMessage());
|
||||
logger.error(MessageFormat.format(Messages.getString("SCRIPT_ERR"), e.getMessage()));
|
||||
throw new MossWorldLoadException(
|
||||
Messages.getString("ScriptEnv.ERR_SCRIPT_ERR") + e.getMessage() + "\r\n" + e.getScriptStackTrace(), e); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
MessageFormat.format(Messages.getString("ScriptEnv.ERR_SCRIPT_ERR"), e.getMessage()) + "\r\n" + e.getScriptStackTrace(), e); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} catch (Error e) {
|
||||
// We are really screwed with classloading if we reach this block
|
||||
logger.fatal("Caught error of type " + e.getClass().getName() + " with toString() of: " + e.toString() + ". This should not happen and implies a severe classloading error.");
|
||||
logger.fatal(MessageFormat.format(Messages.getString("CLASSLOADER_FAIL"), e.getClass().getName(), e.getLocalizedMessage()));
|
||||
}
|
||||
return ScriptResult.RESULT_EXECUTED;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ EventProcessor.THREAD_NAME_MGR=EventProcessorManager
|
|||
EventProcessor.THREADGROUP=EventProcessor
|
||||
FuturesProcessor.FUTURES_THREAD=futures
|
||||
LocalRenderPreparator.MG_EXCEPT=The map generator has thrown an exception.
|
||||
LocalRenderPreparator.MSG_REQUESTED=REQUESTED
|
||||
LocalRenderPreparator.MSG_REQUESTED=Requested chunk {0}, {1}, {2}.
|
||||
LocalRenderPreparator.START_MSG=The local render preparator is starting.
|
||||
MapChunk.BAD_SER_VER=Incorrect serialization version
|
||||
MapDatabase.ERR_DB_FAIL=Database loading failed.
|
||||
|
@ -32,19 +32,100 @@ MossDebugUtils.MSG_TOTAL_SPACE=Total space (bytes):
|
|||
MossDebugUtils.MSG_USABLE_SPACE=Usable space (bytes):
|
||||
MossGame.CFG_LOAD_ERR=Error in loading the configuration file.
|
||||
MossGame.DIR_OR_CFG_NOT_FOUND=Game directory or configuration file not found.
|
||||
MossGame.FILE_NOT_FOUND=file not found:
|
||||
MossGame.FILE_NOT_FOUND=File {0} was not found.
|
||||
MossScript.[NAME]_NOT_FOUND=\ not found\!
|
||||
MossScript.MSG_IO_EXCEPTION=IOException with script named
|
||||
MossScript.MSG_OOPS=Extremely unexpected situation on our hands
|
||||
MossScript.MSG_SCRIPT_NAMED_[NAME]=Script named
|
||||
MossTest.PORT_DESC=Port number to use
|
||||
MossTest.RUN_STANDALONE=Run as standalone server
|
||||
MossWorld.ERR_DB=An error has occured when opening the database. It is likely inaccessible, on a full disk, or corrupt.
|
||||
MossWorld.ERR_DB=An error has occurred when opening the database. It is likely inaccessible, on a full disk, or corrupt.
|
||||
MossWorld.MG_SELECT_FAILURE=The map generator could not be seeded.
|
||||
MossWorld.NO_GAME_ID=The game ID is not specified. The game ID must be specified in game.xml as <gameid>foo</gameid> where data/games/foo is a directory with a valid game.
|
||||
MossWorld.NO_NETWORKING_NOW=Networking is not complete in this version.
|
||||
NodeManager.DESC_UNKNWN_NODE=An unknown piece of the world
|
||||
ScriptEnv.ERR_SCRIPT_ERR=Script error has occured. Wrapped exception: \n
|
||||
ScriptEnv.ERR_SCRIPT_ERR=Script error has occurred. Wrapped exception: {0} \n
|
||||
ServerNetworkingManager.ACCEPT_THREAD=svrNetAccept
|
||||
ServerNetworkingManager.CONN_THREAD_NAME=connection thread
|
||||
ServerNetworkingManager.THREADGROUP=SvrNetGroup
|
||||
PACKET_INVALID_MAGIC=A packet was received with an invalid magic number and has been dropped.
|
||||
SERVER_CONN_TIMEOUT=The connection to the server has timed out or otherwise failed.
|
||||
FIXME_MESSAGE=Hit a block of code that represents missing functionality. Please file a bug report or otherwise sharply emind the devs.
|
||||
EVENT_PROCESS_EXCEPTION=Caught {0} upon processing an event of type {1}. The exception message was {2}.
|
||||
FUTURES_QUEUE_INTERRUPTED=InterruptedException in futures processor trying to take from queue.
|
||||
MOSS_CLIENT_STARTING=Mosstest client starting...
|
||||
LDR_EXEC_EXCEPTION=Loader threw ExecutionException with message {0}
|
||||
LDR_EXCEPTION=Loader threw Exception with message {0}
|
||||
GC_EVICT=Un-caching {0} due to garbage collection. Memory may be low.
|
||||
UNCACHE_EXPIRE=Un-caching {0} as it has expired.
|
||||
EVICT_SIZE=Un-caching {0} due to a size constraint.
|
||||
FILE_OPEN_FAILED=Failed to open file\: {0}
|
||||
HASH_SUCCESS=Hashed {0} as {1}
|
||||
ALGO_NOT_FOUND=Could not find algorithm SHA-256 while hashing {0}
|
||||
NORMALIZE_FAILED=Failed to normalize game resource filename\: {0}
|
||||
GOT_LOCAL_FILE=Got local file {0} as {1}
|
||||
INDEXED_NORMALIZE_FAILURE=Failed to normalize game resource filename from index\: {0}
|
||||
INDEXED_NOT_ON_DISK=File was in index but not on disk\: {0}
|
||||
NO_INDEX=No index file found; all files will be served to the client.
|
||||
FOUND_RECURSIVELY=Got file via recursive directory listing\: {0}
|
||||
RECURSIVE_LISTED_BUT_NOT_FOUND=Could not find file from recursive directory listing. This should never happen.
|
||||
CIRCULAR_DEPENDENCY_ISSUE=A circular dependency was found. {0} depends on {1} but the latter depends directly or indirectly on the former
|
||||
DEPFIND_STACK_OVERFLOW=FIXME The stack overflowed while resolving dependencies. Either there is an undetected dependency issue, or there is simply an extreme number of dependencies.
|
||||
SCRIPT_XML_MISSING=No script.xml has been given, assuming no dependencies and defaults for all other script settings.
|
||||
FAILED_NORMALIZE_RSRC=Failed to normalize game resource filename\: {0}
|
||||
CHUNK_LDR_EXECUTION_EXCEPTION=Chunk loader threw ExecutionException with message {0}
|
||||
RELOADING_INTO_CACHE=Re-loading {0} into cache.
|
||||
FAIL_BUILD_MAPCHUNK_FATAL=IOException caught constructing a MapChunk, and being rethrown as a MosstestFatalDeathException. The world is GOING DOWN NOW.
|
||||
LIGHT_DATA_IOEXCEPTION=IOException writing light chunk data
|
||||
DB_LOAD_IOEXCEPTION=IOException in database loading\: {0}
|
||||
DB_NORMAL_LOAD=Database loaded normally.
|
||||
DB_SHUTDOWN_NORMAL=Database shutting down (normally)
|
||||
DB_SHUTDOWN_EMERGENCY=Map database performed emergency shutdown after catching MosstestFatalDeathException
|
||||
DB_EMERGENCY_SHUTDOWN_FAIL=Map database failed emergency shutdown\: {0}
|
||||
CAUGHT_EXCEPTION_WRITING_STACKTRACE={0} caught trying to write stacktrace of an existing exception. Message\: {1}
|
||||
SECURITY_MANAGER_TESTMODE=WARNING\! The security manager is running in test mode. Security may be diminished.
|
||||
NO_CLASSDIR=Failed to obtain a class directory for the security manager, spurious classloading failures may result.
|
||||
PERMISSION_REQUESTED=Requested permssion {0}
|
||||
ARBITRARY_PERMISSIONS=MosstestSecurityManager prevented the use of arbitrary permissions outside engine contexts.
|
||||
SECURITY_TRUSTED_BASEDIR=The security manager prevented an attempt to set the trusted base directory.
|
||||
THREAD_LOCKED=The security manager prevented an attempt to lock it on an already-locked thread.
|
||||
SECURITY_MISMATCHED_KEY=The security manager prevented an attempt to unlock it using a mismatched key.
|
||||
SECURITY_PEER_CHANGE=MosstestSecurityManager prevented a non-engine-context thread from changing the connected peer.
|
||||
THREAD_ELEVATED=A thread has started without inheriting a thread context and has been elevated
|
||||
THREAD_CONTEXT_NON_ENGINE_CODE=Attempted to set the thread context type from non-engine code
|
||||
SECURITY_CLASSLOADER=MosstestSecurityManager stopped an attempt to create a classloader
|
||||
SECURITY_THREAD=MosstestSecurityManager stopped an attempt to stop or modify a thread
|
||||
SECURITY_THREADGROUP=MosstestSecurityManager stopped an attempt to modify a ThreadGroup
|
||||
SECURITY_EXIT=MosstestSecurityManager stopped an attempt to exit Mosstest improperly from a script
|
||||
SECURITY_SPAWN_PROC=MosstestSecurityManager does not allow any script or portion of the engine to start a new process
|
||||
SECURITY_LINK=MosstestSecurityManager stopped an attempt to link to a JNI library from insecure code
|
||||
SECURITY_READFILE=MosstestSecurityManager stopped an attempt to read {0} from non-core code
|
||||
SECURITY_READ=MosstestSecurityManager stopped an attempt to read {0} from non-core code
|
||||
SECURITY_WRITE=MosstestSecurityManager stopped an attempt to write to a file from non-core code
|
||||
SECURITY_DELETE=MosstestSecurityManager stopped an attempt to delete a file from non-core code
|
||||
SECURITY_CONNECT=MosstestSecurityManager stopped an attempt to connect directly to a network port.
|
||||
SECURITY_LISTEN=MosstestSecurityManager stopped an attempt to listen directly on a network port.
|
||||
SECURITY_BAD_KEY=A mismatched key has been used to unlock this thread.
|
||||
ALREADY_LOCKED=The security manager is already locked for this thread.
|
||||
NO_SET_BASEDIR=Cannot set base directory.
|
||||
MULTICAST=MosstestSecurityManager has denied a script use of multicast directly without use of loadbalancing features
|
||||
MULTICAST2=Scripts may not use mutlicast under any circumstances, except through the engine loadbalancing features
|
||||
SYS_PROPERTIES=MosstestSecurityManager has denied a thread running outside the engine context the right to access system properties.
|
||||
SYS_PROPERTIES_SHORT=Scripts may not access system properties
|
||||
SYS_PROPERTIES_SHORT_NAMED=Scripts may not access system properties. Attempt was to access {0}.
|
||||
TOP_LEVEL=MosstestSecurityManager has blocked a thread running outside the engine context from opening a top-level window.
|
||||
TOP_LEVEL_SHORT=Threads in lockdown may not create top-level windows
|
||||
PRINT=MosstestSecurityManager has denied a thread running outside the engine context the right to access system print jobs.
|
||||
PRINT_SHORT=Print job access is not allowed for the engine or scripts
|
||||
CLIPBOARD=MosstestSecurityManager has prevented a thread in lockdown from accessing the system clipboard.
|
||||
CLIPBOARD_SHORT=Threads in lockdown may not access the system clipboard
|
||||
AWT_QUEUE=MosstestSecurityManager has prevented a thread in lockdown from accessing the AWT queue.
|
||||
AWT_QUEUE_SHORT=Threads in lockdown may not access the AWT queue
|
||||
SYS_FACTORY=MosstestSecurityManager has prevented a thread from setting a Java system factory.
|
||||
SYS_FACTORY_SHORT=Non-engine threads may not set java system factories
|
||||
PLUGIN_CTRL=MosstestSecurityManager has prevented a plugin from controlling certain portions of the Mosstest engine.
|
||||
CTRL_SHORT=Non-engine threads may not control Mosstest execution
|
||||
GAME_CFG_DATA_GONE=The configuration data for the game could not be found, or is empty.
|
||||
SCRIPT_IOEXCEPTION=An IOException has resulted while running {0}. The message was\: {1}
|
||||
SCRIPT_ERR=A script error has occured\: {0}
|
||||
CLASSLOADER_FAIL=Caught error of type {0} with message of\: {1}. This should not happen and implies a severe classloading error.
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package net.mosstest.servercore.serialization;
|
||||
|
||||
public interface IByteArrayConstructor<T> {
|
||||
public T construct(byte[] buf);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package net.mosstest.servercore.serialization;
|
||||
|
||||
public interface IByteArrayWriteable {
|
||||
public byte[] toBytes();
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package net.mosstest.servercore.serialization;
|
||||
|
||||
public interface IManaged<T> {
|
||||
public void setManager(T t);
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
package net.mosstest.servercore;
|
||||
package net.mosstest.servercore.serialization;
|
||||
|
||||
import com.google.common.cache.*;
|
||||
import net.mosstest.servercore.Messages;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.iq80.leveldb.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -16,19 +18,23 @@ import java.util.concurrent.ExecutionException;
|
|||
* @param <K> Keys to be stored
|
||||
* @param <V> Values to be stored
|
||||
*/
|
||||
public class LevelDBBackedMap<K extends AbstractByteArrayStorable<?>, V extends AbstractByteArrayStorable<M>, M> implements Map<K, V> {
|
||||
private final Class<V> valueClass;
|
||||
// V need not extend any sort of marker interface, having a proper constructor passed in takes care of that.
|
||||
public class LevelDBBackedMap<K extends IByteArrayWriteable, V extends IByteArrayWriteable> implements Map<K, V> {
|
||||
// TODO a map backed by a levelDB datastore
|
||||
|
||||
// the in-memory cache
|
||||
private LoadingCache<K, V> memoryBackingCache;
|
||||
|
||||
// a method reference to the constructor to be used in instantiating V from disk. ManagedMap and other subtypes may need to use this constructor.
|
||||
protected IByteArrayConstructor<V> constructor;
|
||||
|
||||
private DB diskBackingDatastore;
|
||||
protected DB diskBackingDatastore;
|
||||
private static final Logger logger = Logger.getLogger(LevelDBBackedMap.class);
|
||||
private BackedMapCacheLoader loader = new BackedMapCacheLoader();
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
// memoryBackingCache.size() is a long
|
||||
if (memoryBackingCache.size() > Integer.MAX_VALUE) return Integer.MAX_VALUE;
|
||||
else return (int) memoryBackingCache.size();
|
||||
}
|
||||
|
@ -54,13 +60,13 @@ public class LevelDBBackedMap<K extends AbstractByteArrayStorable<?>, V extends
|
|||
try {
|
||||
v = memoryBackingCache.get((K) key);
|
||||
} catch (ExecutionException e) {
|
||||
logger.error("Loader threw ExecutionException: " + e);
|
||||
logger.error(MessageFormat.format(Messages.getString("LDR_EXEC_EXCEPTION"), e.getMessage()));
|
||||
}
|
||||
if (v == null) {
|
||||
try {
|
||||
v = loader.load((K) key);
|
||||
} catch (Exception e) {
|
||||
logger.error("Loader threw exception: " + e);
|
||||
logger.error(MessageFormat.format(Messages.getString("LDR_EXCEPTION"), e.getMessage()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -87,8 +93,8 @@ public class LevelDBBackedMap<K extends AbstractByteArrayStorable<?>, V extends
|
|||
public V remove(Object key) {
|
||||
this.memoryBackingCache.invalidate(key);
|
||||
this.memoryBackingCache.asMap().remove(key);
|
||||
if (key instanceof AbstractByteArrayStorable)
|
||||
this.diskBackingDatastore.delete(((AbstractByteArrayStorable) key).toBytes());
|
||||
if (key instanceof IByteArrayWriteable)
|
||||
this.diskBackingDatastore.delete(((IByteArrayWriteable) key).toBytes());
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -111,17 +117,22 @@ public class LevelDBBackedMap<K extends AbstractByteArrayStorable<?>, V extends
|
|||
|
||||
/**
|
||||
* Clears the entire cache and database. This will use a snapshot, so any new entries added on another thread will not be deleted.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void clearDb() throws IOException {
|
||||
this.clear();
|
||||
Snapshot s = diskBackingDatastore.getSnapshot();
|
||||
for(DBIterator dbi = diskBackingDatastore.iterator(new ReadOptions().verifyChecksums(false).snapshot(s)); dbi.hasNext();){
|
||||
for (DBIterator dbi = diskBackingDatastore.iterator(new ReadOptions().snapshot(s)); dbi.hasNext(); ) {
|
||||
Entry<byte[], byte[]> entry = dbi.next();
|
||||
// try a remove
|
||||
dbi.remove();
|
||||
// this may cause a ConcurrentModificationException, testing needed
|
||||
diskBackingDatastore.delete(entry.getKey(), new WriteOptions().sync(false));
|
||||
}
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return memoryBackingCache.asMap().keySet();
|
||||
|
@ -137,19 +148,21 @@ public class LevelDBBackedMap<K extends AbstractByteArrayStorable<?>, V extends
|
|||
return memoryBackingCache.asMap().entrySet();
|
||||
}
|
||||
|
||||
private M manager;
|
||||
|
||||
public LevelDBBackedMap(DB diskBackingDatastore, Class<V> valueClass) {
|
||||
this(diskBackingDatastore, valueClass, false);
|
||||
public LevelDBBackedMap(DB diskBackingDatastore, IByteArrayConstructor<V> constructor) {
|
||||
this(diskBackingDatastore, constructor, false);
|
||||
}
|
||||
|
||||
public LevelDBBackedMap(DB diskBackingDatastore, Class<V> valueClass, boolean soft) {
|
||||
public LevelDBBackedMap(DB diskBackingDatastore, IByteArrayConstructor<V> constructor, boolean soft) {
|
||||
this.constructor = constructor;
|
||||
this.diskBackingDatastore = diskBackingDatastore;
|
||||
this.valueClass = valueClass;
|
||||
this.initMap0(soft, valueClass);
|
||||
this.initMap0(soft);
|
||||
}
|
||||
|
||||
private void initMap0(boolean soft, Class<V> valueClass) {
|
||||
protected LevelDBBackedMap(DB diskBackingDatastore, IByteArrayConstructor<V> constructor, boolean soft, boolean override) {
|
||||
this(diskBackingDatastore, constructor, soft);
|
||||
}
|
||||
|
||||
private void initMap0(boolean soft) {
|
||||
CacheBuilder builder = CacheBuilder.newBuilder();
|
||||
if (soft) builder.softValues();
|
||||
|
||||
|
@ -159,55 +172,72 @@ public class LevelDBBackedMap<K extends AbstractByteArrayStorable<?>, V extends
|
|||
this.memoryBackingCache = checkedCacheBuilder.build(new BackedMapCacheLoader());
|
||||
}
|
||||
|
||||
public LevelDBBackedMap(M manager, DB diskBackingDatastore, Class<V> valueClass, boolean soft) {
|
||||
this.manager = manager;
|
||||
this.diskBackingDatastore = diskBackingDatastore;
|
||||
this.valueClass = valueClass;
|
||||
this.initMap0(soft, valueClass);
|
||||
protected void initMap0(boolean soft, CacheLoader<K, V> loader) {
|
||||
CacheBuilder builder = CacheBuilder.newBuilder();
|
||||
if (soft) builder.softValues();
|
||||
|
||||
// need this odd assignment as per javadoc of CacheBuilder#removalListener()
|
||||
CacheBuilder<K, V> checkedCacheBuilder = builder.removalListener(new BackedMapRemovalListener());
|
||||
|
||||
this.memoryBackingCache = checkedCacheBuilder.build(loader);
|
||||
}
|
||||
|
||||
|
||||
private class BackedMapRemovalListener implements RemovalListener<K, V> {
|
||||
|
||||
@Override
|
||||
public void onRemoval(RemovalNotification<K, V> notification) {
|
||||
switch (notification.getCause()) {
|
||||
case COLLECTED:
|
||||
logger.warn("Un-cacahing " + notification.getKey().toString() + " due to GC. Memory may be low.");
|
||||
logger.warn(MessageFormat.format(Messages.getString("GC_EVICT"), notification.getKey().toString()));
|
||||
break;
|
||||
case EXPIRED:
|
||||
logger.info("Un-cacahing " + notification.getKey().toString() + " as it expired");
|
||||
logger.info(MessageFormat.format(Messages.getString("UNCACHE_EXPIRE"), notification.getKey().toString()));
|
||||
case SIZE:
|
||||
logger.warn("Un-cacahing " + notification.getKey().toString() + " due to a size constraint");
|
||||
logger.warn(MessageFormat.format(Messages.getString("EVICT_SIZE"), notification.getKey().toString()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private class BackedMapCacheLoader extends CacheLoader<K, V> {
|
||||
|
||||
|
||||
@Override
|
||||
public V load(K k) throws Exception {
|
||||
V v = null;
|
||||
byte[] buf = diskBackingDatastore.get(k.toBytes());
|
||||
// nothing in the DB...
|
||||
if (buf == null) return null;
|
||||
//now we can safely pass a not-null byte array
|
||||
return LevelDBBackedMap.this.constructor.construct(diskBackingDatastore.get(k.toBytes()));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (manager == null) {
|
||||
v = (V) valueClass.newInstance();
|
||||
} else {
|
||||
v = (V) valueClass.newInstance();
|
||||
}
|
||||
v.setManager(manager);
|
||||
v.loadBytes(buf);
|
||||
public static class ManagedMap<K extends IByteArrayWriteable, V extends IByteArrayWriteable & IManaged<M>, M> extends LevelDBBackedMap<K, V> {
|
||||
protected M manager;
|
||||
|
||||
public ManagedMap(DB diskBackingDatastore, IByteArrayConstructor<V> constructor, M manager) {
|
||||
super(diskBackingDatastore, constructor, false, true);
|
||||
this.initMap0(false, new ManagedCacheLoader());
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
System.err.println(e.getMessage());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
public ManagedMap(DB diskBackingDatastore, IByteArrayConstructor<V> constructor, boolean soft, M manager) {
|
||||
super(diskBackingDatastore, constructor, soft, true);
|
||||
this.initMap0(soft, new ManagedCacheLoader());
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
private class ManagedCacheLoader extends CacheLoader<K, V> {
|
||||
|
||||
@Override
|
||||
public V load(K key) throws Exception {
|
||||
byte[] buf = diskBackingDatastore.get(key.toBytes());
|
||||
if (buf == null) return null;
|
||||
//now we can safely pass a not-null byte array
|
||||
V v = ManagedMap.this.constructor.construct(diskBackingDatastore.get(key.toBytes()));
|
||||
v.setManager(ManagedMap.this.manager);
|
||||
return v;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
package net.mosstest.swingui;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
|
||||
|
||||
|
||||
import java.awt.MouseInfo;
|
||||
import java.awt.Point;
|
||||
import java.awt.PointerInfo;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
/**
|
||||
* The listener interface for receiving dnD events.
|
||||
* The class that is interested in processing a dnD
|
||||
* event implements this interface, and the object created
|
||||
* with that class is registered with a component using the
|
||||
* component's <code>addDnDListener<code> method. When
|
||||
* the dnD event occurs, that object's appropriate
|
||||
* method is invoked.
|
||||
*
|
||||
* @see DnDEvent
|
||||
*/
|
||||
public class DnDListener implements MouseListener {
|
||||
|
||||
/** The start y. */
|
||||
private double startX, startY;
|
||||
|
||||
/** The end y. */
|
||||
private double endX, endY;
|
||||
|
||||
/** The holder. */
|
||||
private JLabel holder;
|
||||
|
||||
/**
|
||||
* Instantiates a new dn d listener.
|
||||
*
|
||||
* @param parent the parent
|
||||
*/
|
||||
public DnDListener (JLabel parent) {
|
||||
startX = 0;
|
||||
startY = 0;
|
||||
endX = 0;
|
||||
endY = 0;
|
||||
holder = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the diagnostics.
|
||||
*/
|
||||
public void printDiagnostics () {
|
||||
System.out.println("START X: "+startX+" START Y: "+startY);
|
||||
System.out.println("END X: "+endX+" END Y: "+endY);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
|
||||
*/
|
||||
@Override
|
||||
public void mousePressed(MouseEvent arg0) {
|
||||
PointerInfo info = MouseInfo.getPointerInfo();
|
||||
Point location = info.getLocation();
|
||||
startX = location.getX();
|
||||
startY = location.getY();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
|
||||
*/
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent arg0) {
|
||||
PointerInfo info = MouseInfo.getPointerInfo();
|
||||
Point location = info.getLocation();
|
||||
endX = location.getX() - 35; //35, 60: modifiers that need to be present or there
|
||||
endY = location.getY() - 60; //is a significant offset when placement occurs.
|
||||
holder.setLocation((int)endX, (int)endY);
|
||||
printDiagnostics();
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
|
||||
*/
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent arg0) {
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
|
||||
*/
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent arg0) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
|
||||
*/
|
||||
@Override
|
||||
public void mouseExited(MouseEvent arg0) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package net.mosstest.swingui;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
|
||||
/**
|
||||
* The Class ItemSlot.
|
||||
*/
|
||||
public class ItemSlot extends JLabel {
|
||||
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package net.mosstest.swingui;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
/**
|
||||
* The Class SwingDragDrop.
|
||||
*/
|
||||
public class SwingDragDrop {
|
||||
|
||||
/** The frame. */
|
||||
static JFrame frame;
|
||||
|
||||
/** The picture. */
|
||||
static JLabel picture;
|
||||
|
||||
/**
|
||||
* The main method.
|
||||
*
|
||||
* @param args the arguments
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
setupFrame();
|
||||
setupLabels();
|
||||
frame.repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup frame.
|
||||
*/
|
||||
public static void setupFrame() {
|
||||
frame = new JFrame("Drag and Drop Test");
|
||||
frame.setSize(800, 600);
|
||||
frame.setVisible(true);
|
||||
frame.setLayout(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup labels.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public static void setupLabels() throws IOException {
|
||||
ImageIcon icon = new ImageIcon(ImageIO
|
||||
.read(new File("item_switch.png")).getScaledInstance(64, 64,
|
||||
Image.SCALE_REPLICATE));
|
||||
picture = new JLabel(icon);
|
||||
picture.setSize(64, 64);
|
||||
picture.setLocation(200, 200);
|
||||
picture.addMouseListener(new DnDListener(picture));
|
||||
frame.add(picture);
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ public class MockNodeManager implements INodeManager {
|
|||
* The Constant MOCK_SOLID_MAPNODE.
|
||||
*/
|
||||
private static final MapNode MOCK_SOLID_MAPNODE = new MapNode(
|
||||
new DefaultNodeParams(), "mock.png", "!mock:mock", "Mock node", 1);
|
||||
new DefaultNodeParams(), "mock.png", "!mock:mock", "Mock node", 1); //NON-NLS NON-NLS NON-NLS
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see net.mosstest.servercore.INodeManager#getNode(short)
|
||||
|
|
|
@ -2,9 +2,8 @@ package net.mosstest.tests;
|
|||
|
||||
import net.mosstest.scripting.MapChunk;
|
||||
import net.mosstest.scripting.Position;
|
||||
import net.mosstest.scripting.SimplexMapGenerator;
|
||||
import net.mosstest.servercore.AbstractByteArrayStorable;
|
||||
import net.mosstest.servercore.LevelDBBackedMap;
|
||||
import net.mosstest.servercore.serialization.IByteArrayWriteable;
|
||||
import net.mosstest.servercore.serialization.LevelDBBackedMap;
|
||||
import net.mosstest.servercore.MapGeneratorException;
|
||||
import org.junit.Test;
|
||||
import org.junit.Assert;
|
||||
|
@ -16,7 +15,7 @@ public class LevelDBBackedMapTest {
|
|||
|
||||
@Test
|
||||
public void testBasicStore() throws MapGeneratorException, IOException {
|
||||
LevelDBBackedMap<TestByteArrayStorable, TestByteArrayStorable, Void> map = new LevelDBBackedMap<>(new MockDB(), TestByteArrayStorable.class);
|
||||
LevelDBBackedMap<TestByteArrayStorable, TestByteArrayStorable> map = new LevelDBBackedMap<>(new MockDB(), TestByteArrayStorable::new);
|
||||
TestByteArrayStorable testKey = new TestByteArrayStorable(new byte[]{1,2});
|
||||
TestByteArrayStorable testVal = new TestByteArrayStorable(new byte[]{3,4});
|
||||
map.put(testKey, testVal);
|
||||
|
@ -25,14 +24,14 @@ public class LevelDBBackedMapTest {
|
|||
}
|
||||
@Test
|
||||
public void testDbLookup() throws IOException {
|
||||
LevelDBBackedMap<TestByteArrayStorable, TestByteArrayStorable, Void> map = new LevelDBBackedMap<>(new MockDB(), TestByteArrayStorable.class);
|
||||
LevelDBBackedMap<TestByteArrayStorable, TestByteArrayStorable> map = new LevelDBBackedMap<>(new MockDB(), TestByteArrayStorable::new);
|
||||
TestByteArrayStorable vOut = map.get(new TestByteArrayStorable(new byte[]{1,2}));
|
||||
Assert.assertNotNull(vOut);
|
||||
}
|
||||
|
||||
@Test(expected = ClassCastException.class)
|
||||
public void testUncheckedKey() throws MapGeneratorException {
|
||||
LevelDBBackedMap<Position, MapChunk, Void> map = new LevelDBBackedMap<>(new MockDB(), MapChunk.class);
|
||||
LevelDBBackedMap<Position, MapChunk> map = new LevelDBBackedMap<>(new MockDB(), MapChunk::new);
|
||||
|
||||
Object notAPosition = new Object();
|
||||
|
||||
|
@ -40,10 +39,10 @@ public class LevelDBBackedMapTest {
|
|||
}
|
||||
|
||||
|
||||
public static class TestByteArrayStorable extends AbstractByteArrayStorable<Void>{
|
||||
public static class TestByteArrayStorable implements IByteArrayWriteable{
|
||||
byte[] buf;
|
||||
|
||||
public TestByteArrayStorable(byte[] buf) throws IOException {
|
||||
public TestByteArrayStorable(byte[] buf) {
|
||||
|
||||
buf = buf;
|
||||
}
|
||||
|
@ -53,15 +52,8 @@ public class LevelDBBackedMapTest {
|
|||
return buf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setManager(Void manager) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBytes(byte[] buf) throws IOException {
|
||||
this.buf = buf;
|
||||
}
|
||||
|
||||
|
||||
public TestByteArrayStorable() {
|
||||
}
|
||||
|
|
|
@ -0,0 +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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +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>
|
Loading…
Reference in New Issue