Merge remote-tracking branch 'origin' into 021214renderer

Conflicts:
	src/net/mosstest/servercore/RenderProcessor.java
master
Aaron Chan 2014-05-11 15:22:11 -04:00
commit 57c2fe19d7
62 changed files with 1675 additions and 1409 deletions

144
dependency-reduced-pom.xml Normal file
View File

@ -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>

View File

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

View File

@ -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
View File

@ -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>

View File

@ -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);

View File

@ -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"

View File

@ -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() {

View File

@ -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() {

View File

@ -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.

View File

@ -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.

View File

@ -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>());

View File

@ -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);

View File

@ -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) +
'}';
}
}

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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);
}
/**

View File

@ -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;
}

View File

@ -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;
/**

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;
}
/**

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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 {
}
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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[]");
}
}
}

View File

@ -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();

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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());
}
}

View File

@ -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);
}
/**

View File

@ -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$

View File

@ -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);
}
}

View File

@ -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$
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}
}

View File

@ -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;
}

View File

@ -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.

View File

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

View File

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

View File

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

View File

@ -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;
}
}
}

View File

@ -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
}
}

View File

@ -1,10 +0,0 @@
package net.mosstest.swingui;
import javax.swing.JLabel;
/**
* The Class ItemSlot.
*/
public class ItemSlot extends JLabel {
}

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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() {
}

View File

@ -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);
}
}

97
zanata.xml Normal file
View File

@ -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>