added server source and VFS and IPC
This commit is contained in:
parent
21d4f39927
commit
63889aa632
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -13,3 +13,7 @@ stable-download/java/spigot_command/world_the_end/*
|
|||
stable-download/java/spigot_command/server.log
|
||||
stable-download/java/bungee_command/proxy*
|
||||
lwjgl-rundir/_eagstorage*
|
||||
sp-server/.gradle
|
||||
sp-server/.settings
|
||||
sp-server/build
|
||||
sp-server/bin
|
15666
javascript/classes_server.js
Normal file
15666
javascript/classes_server.js
Normal file
File diff suppressed because it is too large
Load Diff
1
javascript/classes_server.js.map
Normal file
1
javascript/classes_server.js.map
Normal file
File diff suppressed because one or more lines are too long
16
javascript/servertest.html
Normal file
16
javascript/servertest.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>eaglercraft server</title>
|
||||
<script type="text/javascript" src="classes_server.js"></script>
|
||||
<script type="text/javascript">
|
||||
window.addEventListener("load", function() {
|
||||
document.getElementById("main").addEventListener("click", function() {
|
||||
main();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="main">main</button>
|
||||
</body>
|
||||
</html>
|
13
sp-server/.classpath
Normal file
13
sp-server/.classpath
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="bin/main" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="gradle_scope" value="main"/>
|
||||
<attribute name="gradle_used_by_scope" value="main,test"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" path="src/ipc/java"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
|
||||
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
|
||||
<classpathentry kind="output" path="bin/default"/>
|
||||
</classpath>
|
23
sp-server/.project
Normal file
23
sp-server/.project
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>eaglercraft-sp-server</name>
|
||||
<comment>Project sp-server created by Buildship.</comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
110
sp-server/build.gradle
Normal file
110
sp-server/build.gradle
Normal file
|
@ -0,0 +1,110 @@
|
|||
|
||||
buildscript {
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs "deps"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath name: "gson-2.2.4"
|
||||
classpath name: "joda-time-2.7"
|
||||
classpath name: "jzlib-1.1.3"
|
||||
classpath name: "teavm-classlib-0.7.0-SNAPSHOT"
|
||||
classpath name: "teavm-interop-0.7.0-SNAPSHOT"
|
||||
classpath name: "teavm-jso-0.7.0-SNAPSHOT"
|
||||
classpath name: "teavm-jso-apis-0.7.0-SNAPSHOT"
|
||||
classpath name: "teavm-jso-impl-0.7.0-SNAPSHOT"
|
||||
classpath name: "teavm-platform-0.7.0-SNAPSHOT"
|
||||
classpath name: "teavm-metaprogramming-api-0.7.0-SNAPSHOT"
|
||||
classpath name: "teavm-metaprogramming-impl-0.7.0-SNAPSHOT"
|
||||
classpath name: "teavm-core-0.7.0-SNAPSHOT"
|
||||
classpath name: "teavm-tooling-0.7.0-SNAPSHOT"
|
||||
classpath name: "teavm-cli-0.6.1"
|
||||
classpath name: "teavm-gradle-plugin-1.0.0-patched"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: "java"
|
||||
apply plugin: "eclipse"
|
||||
apply plugin: "io.github.zebalu.teavm-gradle-plugin"
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir "src/main/java"
|
||||
srcDir "src/ipc/java"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs "deps"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation name: "gson-2.2.4"
|
||||
implementation name: "joda-time-2.7"
|
||||
implementation name: "jzlib-1.1.3"
|
||||
implementation name: "teavm-classlib-0.7.0-SNAPSHOT"
|
||||
implementation name: "teavm-interop-0.7.0-SNAPSHOT"
|
||||
implementation name: "teavm-jso-0.7.0-SNAPSHOT"
|
||||
implementation name: "teavm-jso-apis-0.7.0-SNAPSHOT"
|
||||
implementation name: "teavm-jso-impl-0.7.0-SNAPSHOT"
|
||||
implementation name: "teavm-platform-0.7.0-SNAPSHOT"
|
||||
implementation name: "teavm-metaprogramming-api-0.7.0-SNAPSHOT"
|
||||
implementation name: "teavm-metaprogramming-impl-0.7.0-SNAPSHOT"
|
||||
}
|
||||
|
||||
teavm {
|
||||
|
||||
compileScopes = null;
|
||||
minifying = false;
|
||||
maxTopLevelNames = 10000;
|
||||
properties = null;
|
||||
debugInformationGenerated = false;
|
||||
sourceMapsGenerated = false;
|
||||
sourceFilesCopied = false;
|
||||
incremental = false;
|
||||
transformers = null;
|
||||
|
||||
/** Where to save the result */
|
||||
targetDirectory = file("../javascript");
|
||||
|
||||
/** The directory to monitor to decide if compile is up-to-date or not */
|
||||
sourceDirectory = file("src");
|
||||
|
||||
/** How to name the result file. */
|
||||
targetFileName = "classes_server.js";
|
||||
|
||||
/** Which class holds your public static void main(Strin[] args) method */
|
||||
mainClass = "net.lax1dude.eaglercraft.sp.IntegratedServer";
|
||||
|
||||
/** This will be the name of your main method after compilation. */
|
||||
entryPointName = "main";
|
||||
|
||||
classesToPreserve = null;
|
||||
stopOnErrors = false;
|
||||
optimizationLevel = "FULL"; //org.teavm.vm.TeaVMOptimizationLevel.SIMPLE;
|
||||
fastGlobalAnalysis = false;
|
||||
targetType = "JAVASCRIPT"; //org.teavm.tooling.TeaVMTargetType.JAVASCRIPT;
|
||||
cacheDirectory = null;
|
||||
wasmVersion = "V_0x1"; //org.teavm.backend.wasm.render.WasmBinaryVersion.V_0x1;
|
||||
minHeapSize = 4;
|
||||
maxHeapSize = 128;
|
||||
outOfProcess = false;
|
||||
processMemory = 512;
|
||||
longjmpSupported = true;
|
||||
heapDump = false;
|
||||
|
||||
/** Add name of configurations here where to look for jarfiles. */
|
||||
includeJarsFrom = [];
|
||||
|
||||
/** By default teavmc taskd epends on javaCompile task, unless this varaibale is true. */
|
||||
skipJavaCompile = false;
|
||||
}
|
BIN
sp-server/deps/gson-2.2.4-sources.jar
Normal file
BIN
sp-server/deps/gson-2.2.4-sources.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/gson-2.2.4.jar
Normal file
BIN
sp-server/deps/gson-2.2.4.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/joda-time-2.7-sources.jar
Normal file
BIN
sp-server/deps/joda-time-2.7-sources.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/joda-time-2.7.jar
Normal file
BIN
sp-server/deps/joda-time-2.7.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/jzlib-1.1.3-sources.jar
Normal file
BIN
sp-server/deps/jzlib-1.1.3-sources.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/jzlib-1.1.3.jar
Normal file
BIN
sp-server/deps/jzlib-1.1.3.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-classlib-0.7.0-SNAPSHOT-javadoc.jar
Normal file
BIN
sp-server/deps/teavm-classlib-0.7.0-SNAPSHOT-javadoc.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-classlib-0.7.0-SNAPSHOT-sources.jar
Normal file
BIN
sp-server/deps/teavm-classlib-0.7.0-SNAPSHOT-sources.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-classlib-0.7.0-SNAPSHOT.jar
Normal file
BIN
sp-server/deps/teavm-classlib-0.7.0-SNAPSHOT.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-cli-0.6.1.jar
Normal file
BIN
sp-server/deps/teavm-cli-0.6.1.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-core-0.7.0-SNAPSHOT-javadoc.jar
Normal file
BIN
sp-server/deps/teavm-core-0.7.0-SNAPSHOT-javadoc.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-core-0.7.0-SNAPSHOT-sources.jar
Normal file
BIN
sp-server/deps/teavm-core-0.7.0-SNAPSHOT-sources.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-core-0.7.0-SNAPSHOT.jar
Normal file
BIN
sp-server/deps/teavm-core-0.7.0-SNAPSHOT.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-gradle-plugin-1.0.0-patched.jar
Normal file
BIN
sp-server/deps/teavm-gradle-plugin-1.0.0-patched.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-interop-0.7.0-SNAPSHOT-javadoc.jar
Normal file
BIN
sp-server/deps/teavm-interop-0.7.0-SNAPSHOT-javadoc.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-interop-0.7.0-SNAPSHOT-sources.jar
Normal file
BIN
sp-server/deps/teavm-interop-0.7.0-SNAPSHOT-sources.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-interop-0.7.0-SNAPSHOT.jar
Normal file
BIN
sp-server/deps/teavm-interop-0.7.0-SNAPSHOT.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-jso-0.7.0-SNAPSHOT-javadoc.jar
Normal file
BIN
sp-server/deps/teavm-jso-0.7.0-SNAPSHOT-javadoc.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-jso-0.7.0-SNAPSHOT-sources.jar
Normal file
BIN
sp-server/deps/teavm-jso-0.7.0-SNAPSHOT-sources.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-jso-0.7.0-SNAPSHOT.jar
Normal file
BIN
sp-server/deps/teavm-jso-0.7.0-SNAPSHOT.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-jso-apis-0.7.0-SNAPSHOT-javadoc.jar
Normal file
BIN
sp-server/deps/teavm-jso-apis-0.7.0-SNAPSHOT-javadoc.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-jso-apis-0.7.0-SNAPSHOT-sources.jar
Normal file
BIN
sp-server/deps/teavm-jso-apis-0.7.0-SNAPSHOT-sources.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-jso-apis-0.7.0-SNAPSHOT.jar
Normal file
BIN
sp-server/deps/teavm-jso-apis-0.7.0-SNAPSHOT.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-jso-impl-0.7.0-SNAPSHOT-javadoc.jar
Normal file
BIN
sp-server/deps/teavm-jso-impl-0.7.0-SNAPSHOT-javadoc.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-jso-impl-0.7.0-SNAPSHOT-sources.jar
Normal file
BIN
sp-server/deps/teavm-jso-impl-0.7.0-SNAPSHOT-sources.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-jso-impl-0.7.0-SNAPSHOT.jar
Normal file
BIN
sp-server/deps/teavm-jso-impl-0.7.0-SNAPSHOT.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
sp-server/deps/teavm-metaprogramming-api-0.7.0-SNAPSHOT.jar
Normal file
BIN
sp-server/deps/teavm-metaprogramming-api-0.7.0-SNAPSHOT.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
sp-server/deps/teavm-metaprogramming-impl-0.7.0-SNAPSHOT.jar
Normal file
BIN
sp-server/deps/teavm-metaprogramming-impl-0.7.0-SNAPSHOT.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-platform-0.7.0-SNAPSHOT-javadoc.jar
Normal file
BIN
sp-server/deps/teavm-platform-0.7.0-SNAPSHOT-javadoc.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-platform-0.7.0-SNAPSHOT-sources.jar
Normal file
BIN
sp-server/deps/teavm-platform-0.7.0-SNAPSHOT-sources.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-platform-0.7.0-SNAPSHOT.jar
Normal file
BIN
sp-server/deps/teavm-platform-0.7.0-SNAPSHOT.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-tooling-0.7.0-SNAPSHOT-javadoc.jar
Normal file
BIN
sp-server/deps/teavm-tooling-0.7.0-SNAPSHOT-javadoc.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-tooling-0.7.0-SNAPSHOT-sources.jar
Normal file
BIN
sp-server/deps/teavm-tooling-0.7.0-SNAPSHOT-sources.jar
Normal file
Binary file not shown.
BIN
sp-server/deps/teavm-tooling-0.7.0-SNAPSHOT.jar
Normal file
BIN
sp-server/deps/teavm-tooling-0.7.0-SNAPSHOT.jar
Normal file
Binary file not shown.
12
sp-server/settings.gradle
Normal file
12
sp-server/settings.gradle
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
*
|
||||
* Detailed information about configuring a multi-project build in Gradle can be found
|
||||
* in the user manual at https://docs.gradle.org/6.0/userguide/multi_project_builds.html
|
||||
*/
|
||||
|
||||
rootProject.name = 'eaglercraft-sp-server'
|
||||
|
||||
// you eagler
|
|
@ -0,0 +1,44 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
class IPCInputStream extends InputStream {
|
||||
|
||||
private byte[] currentBuffer = null;
|
||||
private int idx = 0;
|
||||
private String errorName = null;
|
||||
|
||||
void feedBuffer(byte[] b) {
|
||||
currentBuffer = b;
|
||||
idx = 0;
|
||||
errorName = null;
|
||||
}
|
||||
|
||||
void nameBuffer(String str) {
|
||||
errorName = str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
try {
|
||||
return ((int)currentBuffer[++idx]) & 0xFF;
|
||||
}catch(ArrayIndexOutOfBoundsException a) {
|
||||
throw new IOException("IPCInputStream buffer underflow" + (errorName == null ? "" : (" while deserializing '" + errorName + "'")), a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte b[], int off, int len) throws IOException {
|
||||
if(idx + len > currentBuffer.length) {
|
||||
throw new IOException("IPCInputStream buffer underflow" + (errorName == null ? "" : (" while deserializing '" + errorName + "'")), new ArrayIndexOutOfBoundsException(idx + len - 1));
|
||||
}
|
||||
if(off + len > b.length) {
|
||||
throw new ArrayIndexOutOfBoundsException(off + len - 1);
|
||||
}
|
||||
System.arraycopy(b, off, currentBuffer, idx, len);
|
||||
idx += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
class IPCOutputStream extends OutputStream {
|
||||
|
||||
private String className = null;
|
||||
private byte[] currentBuffer = null;
|
||||
private int idx = 0;
|
||||
private int originalSize = 0;
|
||||
|
||||
void feedBuffer(byte[] buf, String clazzName) {
|
||||
currentBuffer = buf;
|
||||
idx = 0;
|
||||
originalSize = buf.length;
|
||||
className = clazzName;
|
||||
}
|
||||
|
||||
byte[] returnBuffer() {
|
||||
if(className != null && currentBuffer.length != originalSize) {
|
||||
System.err.println("WARNING: Packet '" + className + "' was supposed to be " + originalSize + " bytes but buffer has grown by " + (currentBuffer.length - originalSize) + " to " + currentBuffer.length + " bytes");
|
||||
}
|
||||
return currentBuffer;
|
||||
}
|
||||
|
||||
void growBuffer(int i) {
|
||||
int ii = currentBuffer.length;
|
||||
int iii = i - ii;
|
||||
if(iii > 0) {
|
||||
byte[] n = new byte[i];
|
||||
System.arraycopy(currentBuffer, 0, n, 0, ii);
|
||||
currentBuffer = n;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
if(idx >= currentBuffer.length) {
|
||||
growBuffer(idx + 1);
|
||||
}
|
||||
currentBuffer[idx] = (byte) b;
|
||||
++idx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte b[], int off, int len) throws IOException {
|
||||
if(idx + len > currentBuffer.length) {
|
||||
growBuffer(idx + len);
|
||||
}
|
||||
System.arraycopy(b, off, currentBuffer, idx, len);
|
||||
idx += len;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket00StartServer implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x00;
|
||||
|
||||
public String worldName;
|
||||
|
||||
public IPCPacket00StartServer() {
|
||||
}
|
||||
|
||||
public IPCPacket00StartServer(String worldName) {
|
||||
this.worldName = worldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldName = bin.readUTF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldName);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket01StopServer implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x01;
|
||||
|
||||
public IPCPacket01StopServer() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket02InitWorld implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x02;
|
||||
|
||||
public String worldName;
|
||||
public byte gamemode;
|
||||
public byte worldType;
|
||||
public String worldArgs;
|
||||
public long seed;
|
||||
public boolean cheats;
|
||||
public boolean structures;
|
||||
public boolean bonusChest;
|
||||
|
||||
public IPCPacket02InitWorld() {
|
||||
}
|
||||
|
||||
public IPCPacket02InitWorld(String worldName, byte gamemode, byte worldType, String worldArgs, long seed, boolean cheats, boolean structures, boolean bonusChest) {
|
||||
this.worldName = worldName;
|
||||
this.gamemode = gamemode;
|
||||
this.worldType = worldType;
|
||||
this.worldArgs = worldArgs;
|
||||
this.seed = seed;
|
||||
this.cheats = cheats;
|
||||
this.structures = structures;
|
||||
this.bonusChest = bonusChest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldName = bin.readUTF();
|
||||
gamemode = bin.readByte();
|
||||
worldType = bin.readByte();
|
||||
worldArgs = bin.readUTF();
|
||||
seed = bin.readLong();
|
||||
cheats = bin.readBoolean();
|
||||
structures = bin.readBoolean();
|
||||
bonusChest = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldName);
|
||||
bin.writeByte(gamemode);
|
||||
bin.writeByte(worldType);
|
||||
bin.writeUTF(worldArgs);
|
||||
bin.writeLong(seed);
|
||||
bin.writeBoolean(cheats);
|
||||
bin.writeBoolean(structures);
|
||||
bin.writeBoolean(bonusChest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldName) + 1 + 1 + IPCPacketBase.strLen(worldArgs) + 8 + 1 + 1 + 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket03DeleteWorld implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x03;
|
||||
|
||||
public String worldName;
|
||||
|
||||
public IPCPacket03DeleteWorld() {
|
||||
}
|
||||
|
||||
public IPCPacket03DeleteWorld(String worldName) {
|
||||
this.worldName = worldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldName = bin.readUTF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldName);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket04RenameWorld implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x04;
|
||||
|
||||
public String worldOldName;
|
||||
public String worldNewName;
|
||||
public boolean copy;
|
||||
|
||||
public IPCPacket04RenameWorld() {
|
||||
}
|
||||
|
||||
public IPCPacket04RenameWorld(String worldOldName, String worldNewName, boolean copy) {
|
||||
this.worldOldName = worldOldName;
|
||||
this.worldNewName = worldNewName;
|
||||
this.copy = copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldOldName = bin.readUTF();
|
||||
worldNewName = bin.readUTF();
|
||||
copy = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldOldName);
|
||||
bin.writeUTF(worldNewName);
|
||||
bin.writeBoolean(copy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldOldName) + IPCPacketBase.strLen(worldNewName) + 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket05RequestData implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x05;
|
||||
|
||||
public static final byte REQUEST_LEVEL_DAT = 0x00;
|
||||
public static final byte REQUEST_LEVEL_EAG = 0x01;
|
||||
public static final byte REQUEST_LEVEL_MCA = 0x02;
|
||||
|
||||
public String worldName;
|
||||
public byte request;
|
||||
|
||||
public IPCPacket05RequestData() {
|
||||
}
|
||||
|
||||
public IPCPacket05RequestData(String worldName, byte request) {
|
||||
this.worldName = worldName;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldName = bin.readUTF();
|
||||
request = bin.readByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldName);
|
||||
bin.writeByte(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldName) + 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket07ImportWorld implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x07;
|
||||
|
||||
public String worldName;
|
||||
public byte[] worldData;
|
||||
|
||||
public IPCPacket07ImportWorld() {
|
||||
}
|
||||
|
||||
public IPCPacket07ImportWorld(String worldName, byte[] worldData, byte worldFormat) {
|
||||
this.worldName = worldName;
|
||||
this.worldData = worldData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldName = bin.readUTF();
|
||||
worldData = new byte[bin.readInt()];
|
||||
bin.readFully(worldData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldName);
|
||||
bin.writeInt(worldData.length);
|
||||
bin.write(worldData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldName) + worldData.length + 4;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket09RequestResponse implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x09;
|
||||
|
||||
public byte[] response;
|
||||
|
||||
public IPCPacket09RequestResponse() {
|
||||
}
|
||||
|
||||
public IPCPacket09RequestResponse(byte[] dat) {
|
||||
this.response = dat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
response = new byte[bin.readInt()];
|
||||
bin.readFully(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeInt(response.length);
|
||||
bin.write(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 4 + response.length;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket0ASetWorldDifficulty implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x0A;
|
||||
|
||||
public byte difficulty;
|
||||
|
||||
public IPCPacket0ASetWorldDifficulty() {
|
||||
}
|
||||
|
||||
public IPCPacket0ASetWorldDifficulty(byte difficulty) {
|
||||
this.difficulty = difficulty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
difficulty = bin.readByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeByte(difficulty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket0BPause implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x0B;
|
||||
|
||||
public boolean pause;
|
||||
|
||||
public IPCPacket0BPause() {
|
||||
}
|
||||
|
||||
public IPCPacket0BPause(boolean pause) {
|
||||
this.pause = pause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
pause = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeBoolean(pause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket0CPlayerChannel implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x0C;
|
||||
|
||||
public String channel;
|
||||
public boolean open;
|
||||
|
||||
public IPCPacket0CPlayerChannel() {
|
||||
}
|
||||
|
||||
public IPCPacket0CPlayerChannel(String channel, boolean open) {
|
||||
this.channel = channel;
|
||||
this.open = open;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
channel = bin.readUTF();
|
||||
open = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(channel);
|
||||
bin.writeBoolean(open);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(channel) + 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket0DProgressUpdate implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x0D;
|
||||
|
||||
public String updateMessage;
|
||||
public float updateProgress;
|
||||
|
||||
public IPCPacket0DProgressUpdate() {
|
||||
}
|
||||
|
||||
public IPCPacket0DProgressUpdate(String updateMessage, float updateProgress) {
|
||||
this.updateMessage = updateMessage == null ? "" : updateMessage;
|
||||
this.updateProgress = updateProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
updateMessage = bin.readUTF();
|
||||
updateProgress = bin.readFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(updateMessage);
|
||||
bin.writeFloat(updateProgress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(updateMessage) + 4;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket0EListWorlds implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x0E;
|
||||
|
||||
public IPCPacket0EListWorlds() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket0FListFiles implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x0F;
|
||||
|
||||
public String path;
|
||||
|
||||
public IPCPacket0FListFiles() {
|
||||
}
|
||||
|
||||
public IPCPacket0FListFiles(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
this.path = bin.readUTF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(path);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket10FileRead implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x10;
|
||||
|
||||
public String file;
|
||||
|
||||
public IPCPacket10FileRead() {
|
||||
}
|
||||
|
||||
public IPCPacket10FileRead(String file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
file = bin.readUTF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(file);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket12FileWrite implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x12;
|
||||
|
||||
public String path;
|
||||
public byte[] data;
|
||||
|
||||
public IPCPacket12FileWrite() {
|
||||
}
|
||||
|
||||
public IPCPacket12FileWrite(String path, byte[] data) {
|
||||
this.path = path;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
path = bin.readUTF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(path);
|
||||
bin.writeInt(data.length);
|
||||
bin.write(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(path) + 4 + data.length;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacket13FileCopyMove implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x13;
|
||||
|
||||
public String fileOldName;
|
||||
public String fileNewName;
|
||||
public boolean copy;
|
||||
|
||||
public IPCPacket13FileCopyMove() {
|
||||
}
|
||||
|
||||
public IPCPacket13FileCopyMove(String fileOldName, String fileNewName, boolean copy) {
|
||||
this.fileOldName = fileOldName;
|
||||
this.fileNewName = fileNewName;
|
||||
this.copy = copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
fileOldName = bin.readUTF();
|
||||
fileNewName = bin.readUTF();
|
||||
copy = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(fileOldName);
|
||||
bin.writeUTF(fileNewName);
|
||||
bin.writeBoolean(copy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(fileOldName) + IPCPacketBase.strLen(fileNewName) + 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class IPCPacket14StringList implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x14;
|
||||
|
||||
public final List<String> stringList;
|
||||
|
||||
public IPCPacket14StringList() {
|
||||
stringList = new ArrayList();
|
||||
}
|
||||
|
||||
public IPCPacket14StringList(String[] list) {
|
||||
stringList = Arrays.asList(list);
|
||||
}
|
||||
|
||||
public IPCPacket14StringList(List<String> list) {
|
||||
stringList = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
stringList.clear();
|
||||
int len = bin.readInt();
|
||||
for(int i = 0; i < len; ++i) {
|
||||
stringList.add(bin.readUTF());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeInt(stringList.size());
|
||||
for(String str : stringList) {
|
||||
bin.writeUTF(str);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
int len = 4;
|
||||
for(String str : stringList) {
|
||||
len += IPCPacketBase.strLen(str);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface IPCPacketBase {
|
||||
|
||||
public void deserialize(DataInput bin) throws IOException;
|
||||
public void serialize(DataOutput bin) throws IOException;
|
||||
public int id();
|
||||
public int size();
|
||||
|
||||
public static int strLen(String s) {
|
||||
int count = 0;
|
||||
for (int i = 0, len = s.length(); i < len; i++) {
|
||||
char ch = s.charAt(i);
|
||||
if (ch <= 0x7F) {
|
||||
count++;
|
||||
} else if (ch <= 0x7FF) {
|
||||
count += 2;
|
||||
} else if (Character.isHighSurrogate(ch)) {
|
||||
count += 4;
|
||||
++i;
|
||||
} else {
|
||||
count += 3;
|
||||
}
|
||||
}
|
||||
return count + 2;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IPCPacketFFProcessKeepAlive implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0xFF;
|
||||
|
||||
public IPCPacketFFProcessKeepAlive() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package net.lax1dude.eaglercraft.sp.ipc;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class IPCPacketManager {
|
||||
|
||||
public static final HashMap<Integer, Class<? extends IPCPacketBase>> mappings = new HashMap();
|
||||
|
||||
public static final IPCInputStream IPC_INPUT_STREAM = new IPCInputStream();
|
||||
public static final IPCOutputStream IPC_OUTPUT_STREAM = new IPCOutputStream();
|
||||
|
||||
public static final DataInputStream IPC_DATA_INPUT_STREAM = new DataInputStream(IPC_INPUT_STREAM);
|
||||
public static final DataOutputStream IPC_DATA_OUTPUT_STREAM = new DataOutputStream(IPC_OUTPUT_STREAM);
|
||||
|
||||
static {
|
||||
mappings.put(IPCPacket00StartServer.ID, IPCPacket00StartServer.class);
|
||||
mappings.put(IPCPacket01StopServer.ID, IPCPacket01StopServer.class);
|
||||
mappings.put(IPCPacket02InitWorld.ID, IPCPacket02InitWorld.class);
|
||||
mappings.put(IPCPacket03DeleteWorld.ID, IPCPacket03DeleteWorld.class);
|
||||
mappings.put(IPCPacket04RenameWorld.ID, IPCPacket04RenameWorld.class);
|
||||
mappings.put(IPCPacket05RequestData.ID, IPCPacket05RequestData.class);
|
||||
mappings.put(IPCPacket07ImportWorld.ID, IPCPacket07ImportWorld.class);
|
||||
mappings.put(IPCPacket09RequestResponse.ID, IPCPacket09RequestResponse.class);
|
||||
mappings.put(IPCPacket0ASetWorldDifficulty.ID, IPCPacket0ASetWorldDifficulty.class);
|
||||
mappings.put(IPCPacket0BPause.ID, IPCPacket0BPause.class);
|
||||
mappings.put(IPCPacket0CPlayerChannel.ID, IPCPacket0CPlayerChannel.class);
|
||||
mappings.put(IPCPacket0DProgressUpdate.ID, IPCPacket0DProgressUpdate.class);
|
||||
mappings.put(IPCPacket0EListWorlds.ID, IPCPacket0EListWorlds.class);
|
||||
mappings.put(IPCPacket0FListFiles.ID, IPCPacket0FListFiles.class);
|
||||
mappings.put(IPCPacket10FileRead.ID, IPCPacket10FileRead.class);
|
||||
mappings.put(IPCPacket12FileWrite.ID, IPCPacket12FileWrite.class);
|
||||
mappings.put(IPCPacket13FileCopyMove.ID, IPCPacket13FileCopyMove.class);
|
||||
mappings.put(IPCPacket14StringList.ID, IPCPacket14StringList.class);
|
||||
mappings.put(IPCPacketFFProcessKeepAlive.ID, IPCPacketFFProcessKeepAlive.class);
|
||||
}
|
||||
|
||||
public static byte[] IPCSerialize(IPCPacketBase pkt) throws IOException {
|
||||
|
||||
IPC_OUTPUT_STREAM.feedBuffer(new byte[1 + pkt.size()], pkt.getClass().getSimpleName());
|
||||
IPC_OUTPUT_STREAM.write(pkt.id());
|
||||
pkt.serialize(IPC_DATA_OUTPUT_STREAM);
|
||||
|
||||
return IPC_OUTPUT_STREAM.returnBuffer();
|
||||
}
|
||||
|
||||
public static IPCPacketBase IPCDeserialize(byte[] pkt) throws IOException {
|
||||
|
||||
IPC_INPUT_STREAM.feedBuffer(pkt);
|
||||
int i = IPC_INPUT_STREAM.read();
|
||||
|
||||
Class<? extends IPCPacketBase> pk = mappings.get(Integer.valueOf(i));
|
||||
if(pk == null) {
|
||||
throw new IOException("Packet type 0x" + Integer.toHexString(i) + " doesn't exist");
|
||||
}
|
||||
|
||||
IPCPacketBase p;
|
||||
try {
|
||||
p = pk.getDeclaredConstructor().newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
|
||||
| NoSuchMethodException | SecurityException e) {
|
||||
throw new RuntimeException("Packet type '" + pk.getSimpleName() + "' could not be constructed", e);
|
||||
}
|
||||
|
||||
IPC_INPUT_STREAM.nameBuffer(pk.getSimpleName());
|
||||
|
||||
p.deserialize(IPC_DATA_INPUT_STREAM);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package net.lax1dude.eaglercraft.sp;
|
||||
|
||||
public class BooleanResult {
|
||||
|
||||
public static final BooleanResult TRUE = new BooleanResult(true);
|
||||
public static final BooleanResult FALSE = new BooleanResult(false);
|
||||
|
||||
public final boolean bool;
|
||||
|
||||
private BooleanResult(boolean b) {
|
||||
bool = b;
|
||||
}
|
||||
|
||||
public static BooleanResult _new(boolean b) {
|
||||
return b ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package net.lax1dude.eaglercraft.sp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.src.EnumGameType;
|
||||
import net.minecraft.src.ILogAgent;
|
||||
import net.minecraft.src.NetworkListenThread;
|
||||
|
||||
public class EAGMinecraftServer extends MinecraftServer {
|
||||
|
||||
public EAGMinecraftServer(File par1File) {
|
||||
super(par1File);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean startServer() throws IOException {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canStructuresSpawn() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumGameType getGameType() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDifficulty() {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHardcore() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDedicatedServer() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCommandBlockEnabled() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkListenThread getNetworkThread() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String shareToLAN(EnumGameType var1, boolean var2) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILogAgent getLogAgent() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
package net.lax1dude.eaglercraft.sp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.teavm.jso.JSBody;
|
||||
import org.teavm.jso.JSFunctor;
|
||||
import org.teavm.jso.typedarrays.ArrayBuffer;
|
||||
import org.teavm.jso.typedarrays.Uint8Array;
|
||||
|
||||
import net.lax1dude.eaglercraft.sp.ipc.*;
|
||||
|
||||
public class IntegratedServer {
|
||||
|
||||
private static final LinkedList<PKT> messageQueue = new LinkedList();
|
||||
|
||||
protected static class PKT {
|
||||
protected final String channel;
|
||||
protected final byte[] data;
|
||||
protected PKT(String channel, byte[] data) {
|
||||
this.channel = channel;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
@JSFunctor
|
||||
private static class WorkerBinaryPacketHandler {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void onMessage(String channel, ArrayBuffer buf) {
|
||||
if(channel == null) {
|
||||
System.err.println("Recieved IPC packet with null channel");
|
||||
return;
|
||||
}
|
||||
|
||||
if(buf == null) {
|
||||
System.err.println("Recieved IPC packet with null buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
Uint8Array a = Uint8Array.create(buf);
|
||||
byte[] pkt = new byte[a.getLength()];
|
||||
for(int i = 0; i < a.getLength(); ++i) {
|
||||
pkt[i] = (byte) a.get(i);
|
||||
}
|
||||
|
||||
messageQueue.add(new PKT(channel, pkt));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void processAsyncMessageQueue() {
|
||||
while(messageQueue.size() > 0) {
|
||||
PKT msg = messageQueue.remove(0);
|
||||
|
||||
if(msg.channel.equals("IPC")) {
|
||||
|
||||
IPCPacketBase packet;
|
||||
try {
|
||||
packet = IPCPacketManager.IPCDeserialize(msg.data);
|
||||
}catch(IOException e) {
|
||||
System.err.print("Failed to deserialize IPC packet: ");
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
int id = packet.id();
|
||||
switch(id) {
|
||||
case IPCPacket00StartServer.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket01StopServer.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket02InitWorld.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket03DeleteWorld.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket04RenameWorld.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket05RequestData.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket07ImportWorld.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket09RequestResponse.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket0ASetWorldDifficulty.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket0BPause.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket0CPlayerChannel.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket0EListWorlds.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket0FListFiles.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket10FileRead.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket12FileWrite.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket13FileCopyMove.ID:
|
||||
|
||||
break;
|
||||
case IPCPacket14StringList.ID:
|
||||
|
||||
break;
|
||||
default:
|
||||
System.err.println("IPC packet type 0x" + Integer.toHexString(id) + " class '" + packet.getClass().getSimpleName() + "' was not handled");
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
System.err.println("Unknown IPC channel: " + msg.channel);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isRunning = false;
|
||||
|
||||
public static void halt() {
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
private static void mainLoop() {
|
||||
processAsyncMessageQueue();
|
||||
}
|
||||
|
||||
@JSBody(params = { "wb" }, script = "onmessage = function(o) { wb(o.ch, o.dat); };")
|
||||
private static native void registerPacketHandler(WorkerBinaryPacketHandler wb);
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
registerPacketHandler(new WorkerBinaryPacketHandler());
|
||||
|
||||
isRunning = true;
|
||||
|
||||
while(isRunning) {
|
||||
|
||||
mainLoop();
|
||||
|
||||
try {
|
||||
Thread.sleep(1l); // allow some async to occur
|
||||
}catch(InterruptedException e) {
|
||||
System.err.println("you eagler");
|
||||
}
|
||||
}
|
||||
|
||||
// yee
|
||||
}
|
||||
|
||||
}
|
53
sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SYS.java
Normal file
53
sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SYS.java
Normal file
|
@ -0,0 +1,53 @@
|
|||
package net.lax1dude.eaglercraft.sp;
|
||||
|
||||
import org.teavm.interop.Async;
|
||||
import org.teavm.interop.AsyncCallback;
|
||||
import org.teavm.jso.JSBody;
|
||||
import org.teavm.jso.JSFunctor;
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.browser.Window;
|
||||
|
||||
import net.lax1dude.eaglercraft.sp.VirtualFilesystem.VFSHandle;
|
||||
|
||||
public class SYS {
|
||||
|
||||
public static final boolean PERSIST;
|
||||
public static final VirtualFilesystem VFS;
|
||||
|
||||
@JSFunctor
|
||||
private interface PromiseHandler extends JSObject {
|
||||
void complete(JSObject result);
|
||||
}
|
||||
|
||||
@Async
|
||||
private static native BooleanResult requestPersist();
|
||||
|
||||
private static void requestPersist(AsyncCallback<BooleanResult> callback) {
|
||||
requestPersist0(res -> callback.complete(BooleanResult._new(res != null)));
|
||||
}
|
||||
|
||||
@JSBody(params = { "callback" }, script = "if(navigator.storage && navigator.storage.persist){"
|
||||
+ "navigator.storage.persist().then(function(persistent) {callback(persistent ? {p:true} : null);});"
|
||||
+ "}else{callback(null);}")
|
||||
private static native void requestPersist0(PromiseHandler callback);
|
||||
|
||||
static {
|
||||
|
||||
PERSIST = requestPersist().bool;
|
||||
|
||||
if(!PERSIST) {
|
||||
Window.alert("PERSISTENT STORAGE NOT AVAILABLE, YOUR BROWSER MAY DELETE YOUR WORLDS!");
|
||||
}
|
||||
|
||||
VFSHandle vh = VirtualFilesystem.openVFS("_net_lax1dude_eaglercraft_sp_VirtualFilesystem_1_5_2");
|
||||
|
||||
if(vh.vfs == null) {
|
||||
Window.alert("COULD NOT INIT FILESYSTEM: " + vh.toString());
|
||||
}
|
||||
|
||||
VFS = vh.vfs;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package net.lax1dude.eaglercraft.sp;
|
||||
|
||||
public class VFSTestClass {
|
||||
|
||||
public static void test(VirtualFilesystem vfs) {
|
||||
/*
|
||||
System.out.println("'test1' exists: " + vfs.getFile("test1").exists());
|
||||
System.out.println("'test1' chars: " + vfs.getFile("test1").getAllChars());
|
||||
System.out.println("'test2' chars: " + vfs.getFile("test2").getAllChars());
|
||||
System.out.println("'test3' chars: " + vfs.getFile("test3").getAllChars());
|
||||
System.out.println("'test2' exists: " + vfs.getFile("test2").exists());
|
||||
System.out.println("'test3' exists: " + vfs.getFile("test3").exists());
|
||||
|
||||
System.out.println("'test1' set chars 'test string 1': " + vfs.getFile("test1").setAllChars("test string 1"));
|
||||
System.out.println("'test2' set chars 'test string 2': " + vfs.getFile("test2").setAllChars("test string 2"));
|
||||
System.out.println("'test3' set chars 'test string 3': " + vfs.getFile("test3").setAllChars("test string 3"));
|
||||
|
||||
System.out.println("'test1' exists: " + vfs.getFile("test1").exists());
|
||||
System.out.println("'test2' exists: " + vfs.getFile("test2").exists());
|
||||
System.out.println("'test3' exists: " + vfs.getFile("test3").exists());
|
||||
|
||||
System.out.println("'test1' chars: " + vfs.getFile("test1").getAllChars());
|
||||
System.out.println("'test2' chars: " + vfs.getFile("test2").getAllChars());
|
||||
System.out.println("'test3' chars: " + vfs.getFile("test3").getAllChars());
|
||||
|
||||
System.out.println("'test3' delete: " + vfs.getFile("test3").delete());
|
||||
System.out.println("'test3' exists: " + vfs.getFile("test3").exists());
|
||||
|
||||
System.out.println("'test2' delete: " + vfs.getFile("test2").delete());
|
||||
System.out.println("'test2' chars: " + vfs.getFile("test2").getAllChars());
|
||||
|
||||
System.out.println("'test4' exists: " + vfs.getFile("test4").exists());
|
||||
System.out.println("'test1' to 'test4' rename: " + vfs.getFile("test1").rename("test4"));
|
||||
System.out.println("'test4' exists: " + vfs.getFile("test4").exists());
|
||||
System.out.println("'test4' chars: " + vfs.getFile("test4").getAllChars());
|
||||
System.out.println("'test1' exists: " + vfs.getFile("test1").exists());
|
||||
System.out.println("'test4' to 'test1' rename: " + vfs.getFile("test4").rename("test1"));
|
||||
System.out.println("'test4' exists: " + vfs.getFile("test4").exists());
|
||||
System.out.println("'test4' chars: " + vfs.getFile("test4").getAllChars());
|
||||
System.out.println("'test1' exists: " + vfs.getFile("test1").exists());
|
||||
System.out.println("'test1' chars: " + vfs.getFile("test1").getAllChars());
|
||||
|
||||
System.out.println("'test1' cache get chars: " + vfs.getFile("test1", true).getAllChars());
|
||||
System.out.println("'test1' cache exists: " + vfs.getFile("test1", true).exists());
|
||||
System.out.println("'test1' cache delete: " + vfs.getFile("test1", true).delete());
|
||||
System.out.println("'test1' cache exists: " + vfs.getFile("test1", true).exists());
|
||||
System.out.println("'test1' cache get chars: " + vfs.getFile("test1", true).getAllChars());
|
||||
|
||||
System.out.println("'test1' cache set chars 'test cache string 1': " + vfs.getFile("test1", true).setAllChars("test cache string 1"));
|
||||
System.out.println("'test2' cache set chars 'test cache string 2': " + vfs.getFile("test2", true).setAllChars("test cache string 2"));
|
||||
System.out.println("'test3' cache set chars 'test cache string 3': " + vfs.getFile("test3", true).setAllChars("test cache string 3"));
|
||||
|
||||
System.out.println("'test1' cache chars: " + vfs.getFile("test1").getAllChars());
|
||||
System.out.println("'test2' cache chars: " + vfs.getFile("test2").getAllChars());
|
||||
System.out.println("'test3' cache chars: " + vfs.getFile("test3").getAllChars());
|
||||
|
||||
System.out.println("'test1' cache copy chars: " + VirtualFilesystem.utf8(vfs.getFile("test1").getAllBytes(true)));
|
||||
System.out.println("'test2' cache copy chars: " + VirtualFilesystem.utf8(vfs.getFile("test2").getAllBytes(true)));
|
||||
System.out.println("'test3' cache copy chars: " + VirtualFilesystem.utf8(vfs.getFile("test3").getAllBytes(true)));
|
||||
*/
|
||||
|
||||
VFile f = new VFile("test1");
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("/test1");
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("/test2/");
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("test2/");
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("test2/teste");
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("\\test2\\teste");
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("\\test2\\teste\\..\\eag");
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("test2", "teste", "eag");
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile(f, "../", "test2", "teste", "eag");
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile(f, "../../", "test2", ".", "eag");
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("you/eag", f);
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile(" you/ eag ", f);
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("\\yee\\", f);
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("\\yee\\", "yeeler", f, new VFile("yee"));
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile(f, new VFile("yee2"));
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("yee/deevler/", new VFile("yee2"));
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("yee/../../../../", new VFile("yee2"));
|
||||
System.out.println(f);
|
||||
|
||||
f = new VFile("yee/../../deevler../../", new VFile("yee2"));
|
||||
System.out.println(f);
|
||||
}
|
||||
|
||||
}
|
213
sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFile.java
Normal file
213
sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFile.java
Normal file
|
@ -0,0 +1,213 @@
|
|||
package net.lax1dude.eaglercraft.sp;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class VFile {
|
||||
|
||||
public static final String pathSeperator = "/";
|
||||
public static final String[] altPathSeperator = new String[] { "\\" };
|
||||
|
||||
public static String normalizePath(String p) {
|
||||
for(int i = 0; i < altPathSeperator.length; ++i) {
|
||||
p = p.replace(altPathSeperator[i], pathSeperator);
|
||||
}
|
||||
if(p.startsWith(pathSeperator)) {
|
||||
p = p.substring(pathSeperator.length());
|
||||
}
|
||||
if(p.endsWith(pathSeperator)) {
|
||||
p = p.substring(0, p.length() - pathSeperator.length());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
public static String[] splitPath(String p) {
|
||||
String[] pth = normalizePath(p).split(pathSeperator);
|
||||
for(int i = 0; i < pth.length; ++i) {
|
||||
pth[i] = pth[i].trim();
|
||||
}
|
||||
return pth;
|
||||
}
|
||||
|
||||
private String path;
|
||||
|
||||
public static String createPath(Object... p) {
|
||||
ArrayList<String> r = new ArrayList();
|
||||
for(int i = 0; i < p.length; ++i) {
|
||||
if(p[i] == null) {
|
||||
continue;
|
||||
}
|
||||
String gg = p[i].toString();
|
||||
if(gg == null) {
|
||||
continue;
|
||||
}
|
||||
String[] parts = splitPath(gg);
|
||||
for(int j = 0; j < parts.length; ++j) {
|
||||
if(parts[j] == null || parts[j].equals(".")) {
|
||||
continue;
|
||||
}else if(parts[j].equals("..") && r.size() > 0) {
|
||||
int k = r.size() - 1;
|
||||
if(!r.get(k).equals("..")) {
|
||||
r.remove(k);
|
||||
}else {
|
||||
r.add("..");
|
||||
}
|
||||
}else {
|
||||
r.add(parts[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(r.size() > 0) {
|
||||
StringBuilder s = new StringBuilder();
|
||||
for(int i = 0; i < r.size(); ++i) {
|
||||
if(i > 0) {
|
||||
s.append(pathSeperator);
|
||||
}
|
||||
s.append(r.get(i));
|
||||
}
|
||||
return s.toString();
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public VFile(Object... p) {
|
||||
this.path = createPath(p);
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return isRelative() ? null : SYS.VFS.getFile(path).getInputStream();
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
return isRelative() ? null : SYS.VFS.getFile(path).getOutputStream();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public boolean isRelative() {
|
||||
return path == null || path.contains("..");
|
||||
}
|
||||
|
||||
public boolean canRead() {
|
||||
return !isRelative() && SYS.VFS.fileExists(path);
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path.equals("unnamed") ? null : path;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
if(path == null) {
|
||||
return null;
|
||||
}
|
||||
int i = path.indexOf(pathSeperator);
|
||||
return i == -1 ? path : path.substring(i + 1);
|
||||
}
|
||||
|
||||
public boolean canWrite() {
|
||||
return !isRelative();
|
||||
}
|
||||
|
||||
public String getParent() {
|
||||
if(path == null) {
|
||||
return null;
|
||||
}
|
||||
int i = path.indexOf(pathSeperator);
|
||||
return i == -1 ? ".." : path.substring(0, i);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return path == null ? 0 : path.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return path != null && o != null && (o instanceof VFile) && path.equals(((VFile)o).path);
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
return !isRelative() && SYS.VFS.fileExists(path);
|
||||
}
|
||||
|
||||
public boolean delete() {
|
||||
return !isRelative() && SYS.VFS.deleteFile(path);
|
||||
}
|
||||
|
||||
public boolean renameTo(String p) {
|
||||
if(!isRelative() && SYS.VFS.renameFile(path, p)) {
|
||||
path = p;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return isRelative() ? -1 : SYS.VFS.getFile(path).getSize();
|
||||
}
|
||||
|
||||
public void getBytes(int fileOffset, byte[] array, int offset, int length) {
|
||||
if(isRelative()) {
|
||||
throw new ArrayIndexOutOfBoundsException("File is relative");
|
||||
}
|
||||
SYS.VFS.getFile(path).getBytes(fileOffset, array, offset, length);
|
||||
}
|
||||
|
||||
public void setCacheEnabled() {
|
||||
if(isRelative()) {
|
||||
throw new RuntimeException("File is relative");
|
||||
}
|
||||
SYS.VFS.getFile(path).setCacheEnabled();
|
||||
}
|
||||
|
||||
public byte[] getAllBytes() {
|
||||
if(isRelative()) {
|
||||
return null;
|
||||
}
|
||||
return SYS.VFS.getFile(path).getAllBytes();
|
||||
}
|
||||
|
||||
public String getAllChars() {
|
||||
if(isRelative()) {
|
||||
return null;
|
||||
}
|
||||
return SYS.VFS.getFile(path).getAllChars();
|
||||
}
|
||||
|
||||
public String[] getAllLines() {
|
||||
if(isRelative()) {
|
||||
return null;
|
||||
}
|
||||
return SYS.VFS.getFile(path).getAllLines();
|
||||
}
|
||||
|
||||
public byte[] getAllBytes(boolean copy) {
|
||||
if(isRelative()) {
|
||||
return null;
|
||||
}
|
||||
return SYS.VFS.getFile(path).getAllBytes(copy);
|
||||
}
|
||||
|
||||
public boolean setAllChars(String bytes) {
|
||||
if(isRelative()) {
|
||||
return false;
|
||||
}
|
||||
return SYS.VFS.getFile(path).setAllChars(bytes);
|
||||
}
|
||||
|
||||
public boolean setAllBytes(byte[] bytes) {
|
||||
if(isRelative()) {
|
||||
return false;
|
||||
}
|
||||
return SYS.VFS.getFile(path).setAllBytes(bytes);
|
||||
}
|
||||
|
||||
public boolean setAllBytes(byte[] bytes, boolean copy) {
|
||||
if(isRelative()) {
|
||||
return false;
|
||||
}
|
||||
return SYS.VFS.getFile(path).setAllBytes(bytes, copy);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,572 @@
|
|||
package net.lax1dude.eaglercraft.sp;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.teavm.interop.Async;
|
||||
import org.teavm.interop.AsyncCallback;
|
||||
import org.teavm.jso.JSBody;
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.dom.events.Event;
|
||||
import org.teavm.jso.dom.events.EventListener;
|
||||
import org.teavm.jso.indexeddb.EventHandler;
|
||||
import org.teavm.jso.indexeddb.IDBCountRequest;
|
||||
import org.teavm.jso.indexeddb.IDBDatabase;
|
||||
import org.teavm.jso.indexeddb.IDBFactory;
|
||||
import org.teavm.jso.indexeddb.IDBGetRequest;
|
||||
import org.teavm.jso.indexeddb.IDBObjectStoreParameters;
|
||||
import org.teavm.jso.indexeddb.IDBOpenDBRequest;
|
||||
import org.teavm.jso.indexeddb.IDBRequest;
|
||||
import org.teavm.jso.indexeddb.IDBTransaction;
|
||||
import org.teavm.jso.indexeddb.IDBVersionChangeEvent;
|
||||
import org.teavm.jso.typedarrays.ArrayBuffer;
|
||||
import org.teavm.jso.typedarrays.Uint8Array;
|
||||
|
||||
public class VirtualFilesystem {
|
||||
|
||||
protected static class VirtualOutputStream extends ByteArrayOutputStream {
|
||||
private final VFSFile file;
|
||||
|
||||
protected VirtualOutputStream(VFSFile file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if(!file.setAllBytes(super.toByteArray(), false)) {
|
||||
throw new IOException("Could not close stream and write to \"" + file.filePath + "\" on VFS \"" + file.virtualFilesystem.database + "\" (the file was probably deleted)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class VFSFile {
|
||||
|
||||
public final VirtualFilesystem virtualFilesystem;
|
||||
protected boolean cacheEnabled;
|
||||
protected String filePath;
|
||||
protected int fileSize = -1;
|
||||
protected boolean hasBeenDeleted = false;
|
||||
protected boolean hasBeenAccessed = false;
|
||||
protected boolean exists = false;
|
||||
|
||||
protected byte[] cache = null;
|
||||
protected long cacheHit;
|
||||
|
||||
protected VFSFile(VirtualFilesystem vfs, String filePath, boolean cacheEnabled) {
|
||||
this.virtualFilesystem = vfs;
|
||||
this.filePath = filePath;
|
||||
this.cacheHit = System.currentTimeMillis();
|
||||
if(cacheEnabled) {
|
||||
setCacheEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof VFSFile) && ((VFSFile)o).filePath.equals(filePath);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return filePath.hashCode();
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
cacheHit = System.currentTimeMillis();
|
||||
if(fileSize < 0) {
|
||||
if(cacheEnabled) {
|
||||
byte[] b = getAllBytes(false);
|
||||
if(b != null) {
|
||||
fileSize = b.length;
|
||||
}
|
||||
}else {
|
||||
ArrayBuffer dat = AsyncHandlers.readWholeFile(virtualFilesystem.indexeddb, filePath);
|
||||
if(dat != null) {
|
||||
fileSize = dat.getByteLength();
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
byte[] dat = getAllBytes(false);
|
||||
if(dat == null) {
|
||||
return null;
|
||||
}
|
||||
return new ByteArrayInputStream(dat);
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
return new VirtualOutputStream(this);
|
||||
}
|
||||
|
||||
public void getBytes(int fileOffset, byte[] array, int offset, int length) {
|
||||
if(hasBeenDeleted) {
|
||||
throw new ArrayIndexOutOfBoundsException("file '" + filePath + "' has been deleted");
|
||||
}else if(hasBeenAccessed && !exists) {
|
||||
throw new ArrayIndexOutOfBoundsException("file '" + filePath + "' does not exist");
|
||||
}
|
||||
cacheHit = System.currentTimeMillis();
|
||||
if(cacheEnabled && cache != null) {
|
||||
System.arraycopy(cache, fileOffset, array, offset, length);
|
||||
}else {
|
||||
ArrayBuffer aa = AsyncHandlers.readWholeFile(virtualFilesystem.indexeddb, filePath);
|
||||
hasBeenAccessed = true;
|
||||
if(aa != null) {
|
||||
exists = true;
|
||||
}else {
|
||||
exists = false;
|
||||
throw new ArrayIndexOutOfBoundsException("file '" + filePath + "' does not exist");
|
||||
}
|
||||
Uint8Array a = Uint8Array.create(aa);
|
||||
this.fileSize = a.getByteLength();
|
||||
if(cacheEnabled) {
|
||||
cache = new byte[fileSize];
|
||||
for(int i = 0; i < fileSize; ++i) {
|
||||
cache[i] = (byte)a.get(i);
|
||||
}
|
||||
}
|
||||
if(a.getLength() < fileOffset + length) {
|
||||
throw new ArrayIndexOutOfBoundsException("file '" + filePath + "' size was "+a.getLength()+" but user tried to read index "+(fileOffset + length - 1));
|
||||
}
|
||||
for(int i = 0; i < length; ++i) {
|
||||
array[i + offset] = (byte)a.get(i + fileOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setCacheEnabled() {
|
||||
if(!cacheEnabled && !hasBeenDeleted && !(hasBeenAccessed && !exists)) {
|
||||
cacheHit = System.currentTimeMillis();
|
||||
cache = getAllBytes(false);
|
||||
cacheEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getAllBytes() {
|
||||
return getAllBytes(false);
|
||||
}
|
||||
|
||||
public String getAllChars() {
|
||||
return utf8(getAllBytes(false));
|
||||
}
|
||||
|
||||
public String[] getAllLines() {
|
||||
return lines(getAllChars());
|
||||
}
|
||||
|
||||
public byte[] getAllBytes(boolean copy) {
|
||||
if(hasBeenDeleted || (hasBeenAccessed && !exists)) {
|
||||
return null;
|
||||
}
|
||||
cacheHit = System.currentTimeMillis();
|
||||
if(cacheEnabled && cache != null) {
|
||||
byte[] b = cache;
|
||||
if(copy) {
|
||||
b = new byte[cache.length];
|
||||
System.arraycopy(cache, 0, b, 0, cache.length);
|
||||
}
|
||||
return b;
|
||||
}else {
|
||||
hasBeenAccessed = true;
|
||||
ArrayBuffer b = AsyncHandlers.readWholeFile(virtualFilesystem.indexeddb, filePath);
|
||||
if(b != null) {
|
||||
exists = true;
|
||||
}else {
|
||||
exists = false;
|
||||
return null;
|
||||
}
|
||||
Uint8Array a = Uint8Array.create(b);
|
||||
this.fileSize = a.getByteLength();
|
||||
byte[] array = new byte[fileSize];
|
||||
for(int i = 0; i < a.getByteLength(); ++i) {
|
||||
array[i] = (byte)a.get(i);
|
||||
}
|
||||
if(cacheEnabled) {
|
||||
if(copy) {
|
||||
cache = new byte[fileSize];
|
||||
System.arraycopy(b, 0, cache, 0, cache.length);
|
||||
}else {
|
||||
cache = array;
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setAllChars(String bytes) {
|
||||
return setAllBytes(utf8(bytes), true);
|
||||
}
|
||||
|
||||
public boolean setAllBytes(byte[] bytes) {
|
||||
return setAllBytes(bytes, true);
|
||||
}
|
||||
|
||||
public boolean setAllBytes(byte[] bytes, boolean copy) {
|
||||
if(hasBeenDeleted || bytes == null) {
|
||||
return false;
|
||||
}
|
||||
cacheHit = System.currentTimeMillis();
|
||||
this.fileSize = bytes.length;
|
||||
if(cacheEnabled) {
|
||||
byte[] copz = bytes;
|
||||
if(copy) {
|
||||
copz = new byte[bytes.length];
|
||||
System.arraycopy(bytes, 0, copz, 0, bytes.length);
|
||||
}
|
||||
cache = copz;
|
||||
return sync();
|
||||
}else {
|
||||
ArrayBuffer a = ArrayBuffer.create(bytes.length);
|
||||
Uint8Array ar = Uint8Array.create(a);
|
||||
ar.set(bytes);
|
||||
boolean s = AsyncHandlers.writeWholeFile(virtualFilesystem.indexeddb, filePath, a).bool;
|
||||
hasBeenAccessed = true;
|
||||
exists = exists || s;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean sync() {
|
||||
if(cacheEnabled && cache != null && !hasBeenDeleted) {
|
||||
cacheHit = System.currentTimeMillis();
|
||||
ArrayBuffer a = ArrayBuffer.create(cache.length);
|
||||
Uint8Array ar = Uint8Array.create(a);
|
||||
ar.set(cache);
|
||||
boolean tryWrite = AsyncHandlers.writeWholeFile(virtualFilesystem.indexeddb, filePath, a).bool;
|
||||
hasBeenAccessed = true;
|
||||
exists = exists || tryWrite;
|
||||
return tryWrite;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean delete() {
|
||||
if(!hasBeenDeleted && !(hasBeenAccessed && !exists)) {
|
||||
cacheHit = System.currentTimeMillis();
|
||||
if(!AsyncHandlers.deleteFile(virtualFilesystem.indexeddb, filePath).bool) {
|
||||
hasBeenAccessed = true;
|
||||
return false;
|
||||
}
|
||||
virtualFilesystem.fileMap.remove(filePath);
|
||||
hasBeenDeleted = true;
|
||||
hasBeenAccessed = true;
|
||||
exists = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean rename(String newName) {
|
||||
if(!hasBeenDeleted && !(hasBeenAccessed && !exists)) {
|
||||
cacheHit = System.currentTimeMillis();
|
||||
ArrayBuffer arr = AsyncHandlers.readWholeFile(virtualFilesystem.indexeddb, filePath);
|
||||
hasBeenAccessed = true;
|
||||
if(arr != null) {
|
||||
exists = true;
|
||||
if(!AsyncHandlers.writeWholeFile(virtualFilesystem.indexeddb, newName, arr).bool) {
|
||||
return false;
|
||||
}
|
||||
if(!AsyncHandlers.deleteFile(virtualFilesystem.indexeddb, filePath).bool) {
|
||||
return false;
|
||||
}
|
||||
}else {
|
||||
exists = false;
|
||||
}
|
||||
virtualFilesystem.fileMap.remove(filePath);
|
||||
filePath = newName;
|
||||
virtualFilesystem.fileMap.put(newName, this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
if(hasBeenDeleted) {
|
||||
return false;
|
||||
}
|
||||
cacheHit = System.currentTimeMillis();
|
||||
if(hasBeenAccessed) {
|
||||
return exists;
|
||||
}
|
||||
exists = AsyncHandlers.fileExists(virtualFilesystem.indexeddb, filePath).bool;
|
||||
hasBeenAccessed = true;
|
||||
return exists;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final HashMap<String, VFSFile> fileMap = new HashMap();
|
||||
|
||||
public final String database;
|
||||
private final IDBDatabase indexeddb;
|
||||
|
||||
public static class VFSHandle {
|
||||
|
||||
public final boolean failedInit;
|
||||
public final boolean failedLocked;
|
||||
public final String failedError;
|
||||
public final VirtualFilesystem vfs;
|
||||
|
||||
public VFSHandle(boolean init, boolean locked, String error, VirtualFilesystem db) {
|
||||
failedInit = init;
|
||||
failedLocked = locked;
|
||||
failedError = error;
|
||||
vfs = db;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if(failedInit) {
|
||||
return "IDBFactory threw an exception, IndexedDB is most likely not supported in this browser." + (failedError == null ? "" : "\n\n" + failedError);
|
||||
}
|
||||
if(failedLocked) {
|
||||
return "The filesystem requested is already in use on a different tab.";
|
||||
}
|
||||
if(failedError != null) {
|
||||
return "The IDBFactory.open() request failed, reason: " + failedError;
|
||||
}
|
||||
return "Virtual Filesystem Object: " + vfs.database;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static VFSHandle openVFS(String db) {
|
||||
DatabaseOpen evt = AsyncHandlers.openDB(db);
|
||||
if(evt.failedInit) {
|
||||
return new VFSHandle(true, false, evt.failedError, null);
|
||||
}
|
||||
if(evt.failedLocked) {
|
||||
return new VFSHandle(false, true, null, null);
|
||||
}
|
||||
if(evt.failedError != null) {
|
||||
return new VFSHandle(false, false, evt.failedError, null);
|
||||
}
|
||||
return new VFSHandle(false, false, null, new VirtualFilesystem(db, evt.database));
|
||||
}
|
||||
|
||||
private VirtualFilesystem(String db, IDBDatabase idb) {
|
||||
database = db;
|
||||
indexeddb = idb;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
indexeddb.close();
|
||||
}
|
||||
|
||||
public VFSFile getFile(String path) {
|
||||
return getFile(path, false);
|
||||
}
|
||||
|
||||
public VFSFile getFile(String path, boolean cache) {
|
||||
VFSFile f = fileMap.get(path);
|
||||
if(f == null) {
|
||||
fileMap.put(path, f = new VFSFile(this, path, cache));
|
||||
}else {
|
||||
if(cache) {
|
||||
f.setCacheEnabled();
|
||||
}
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean renameFile(String oldName, String newName) {
|
||||
return getFile(oldName).rename(newName);
|
||||
}
|
||||
|
||||
public boolean deleteFile(String path) {
|
||||
return getFile(path).delete();
|
||||
}
|
||||
|
||||
public boolean fileExists(String path) {
|
||||
return getFile(path).exists();
|
||||
}
|
||||
|
||||
public void flushCache(long age) {
|
||||
long curr = System.currentTimeMillis();
|
||||
Iterator<VFSFile> files = fileMap.values().iterator();
|
||||
while(files.hasNext()) {
|
||||
if(curr - files.next().cacheHit > age) {
|
||||
files.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static class DatabaseOpen {
|
||||
|
||||
protected final boolean failedInit;
|
||||
protected final boolean failedLocked;
|
||||
protected final String failedError;
|
||||
|
||||
protected final IDBDatabase database;
|
||||
|
||||
protected DatabaseOpen(boolean init, boolean locked, String error, IDBDatabase db) {
|
||||
failedInit = init;
|
||||
failedLocked = locked;
|
||||
failedError = error;
|
||||
database = db;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class AsyncHandlers {
|
||||
|
||||
@Async
|
||||
protected static native DatabaseOpen openDB(String name);
|
||||
|
||||
private static void openDB(String name, final AsyncCallback<DatabaseOpen> cb) {
|
||||
IDBFactory i = null;
|
||||
try {
|
||||
i = IDBFactory.getInstance();
|
||||
}catch(Throwable t) {
|
||||
cb.complete(new DatabaseOpen(true, false, t.toString(), null));
|
||||
}
|
||||
final IDBOpenDBRequest f = i.open(name, 1);
|
||||
f.setOnBlocked(new EventHandler() {
|
||||
@Override
|
||||
public void handleEvent() {
|
||||
cb.complete(new DatabaseOpen(false, true, null, null));
|
||||
}
|
||||
});
|
||||
f.setOnSuccess(new EventHandler() {
|
||||
@Override
|
||||
public void handleEvent() {
|
||||
cb.complete(new DatabaseOpen(false, false, null, f.getResult()));
|
||||
}
|
||||
});
|
||||
f.setOnError(new EventHandler() {
|
||||
@Override
|
||||
public void handleEvent() {
|
||||
cb.complete(new DatabaseOpen(false, false, "open error", null));
|
||||
}
|
||||
});
|
||||
f.setOnUpgradeNeeded(new EventListener<IDBVersionChangeEvent>() {
|
||||
@Override
|
||||
public void handleEvent(IDBVersionChangeEvent evt) {
|
||||
f.getResult().createObjectStore("filesystem", IDBObjectStoreParameters.create().keyPath("path"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Async
|
||||
protected static native BooleanResult deleteFile(IDBDatabase db, String name);
|
||||
|
||||
private static void deleteFile(IDBDatabase db, String name, final AsyncCallback<BooleanResult> cb) {
|
||||
IDBTransaction tx = db.transaction("filesystem", "readwrite");
|
||||
final IDBRequest r = tx.objectStore("filesystem").delete(makeTheFuckingKeyWork(name));
|
||||
|
||||
r.addEventListener("success", new EventListener<Event>() {
|
||||
@Override
|
||||
public void handleEvent(Event evt) {
|
||||
cb.complete(BooleanResult._new(true));
|
||||
}
|
||||
});
|
||||
r.addEventListener("error", new EventListener<Event>() {
|
||||
@Override
|
||||
public void handleEvent(Event evt) {
|
||||
cb.complete(BooleanResult._new(false));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@JSBody(params = { "obj" }, script = "return (typeof obj === 'undefined') ? null : ((typeof obj.data === 'undefined') ? null : obj.data);")
|
||||
protected static native ArrayBuffer readRow(JSObject obj);
|
||||
|
||||
@JSBody(params = { "obj" }, script = "return [obj];")
|
||||
private static native JSObject makeTheFuckingKeyWork(String k);
|
||||
|
||||
@Async
|
||||
protected static native ArrayBuffer readWholeFile(IDBDatabase db, String name);
|
||||
|
||||
private static void readWholeFile(IDBDatabase db, String name, final AsyncCallback<ArrayBuffer> cb) {
|
||||
IDBTransaction tx = db.transaction("filesystem", "readonly");
|
||||
final IDBGetRequest r = tx.objectStore("filesystem").get(makeTheFuckingKeyWork(name));
|
||||
r.addEventListener("success", new EventListener<Event>() {
|
||||
@Override
|
||||
public void handleEvent(Event evt) {
|
||||
cb.complete(readRow(r.getResult()));
|
||||
}
|
||||
});
|
||||
r.addEventListener("error", new EventListener<Event>() {
|
||||
@Override
|
||||
public void handleEvent(Event evt) {
|
||||
cb.complete(null);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Async
|
||||
protected static native BooleanResult fileExists(IDBDatabase db, String name);
|
||||
|
||||
private static void fileExists(IDBDatabase db, String name, final AsyncCallback<BooleanResult> cb) {
|
||||
IDBTransaction tx = db.transaction("filesystem", "readonly");
|
||||
final IDBCountRequest r = tx.objectStore("filesystem").count(makeTheFuckingKeyWork(name));
|
||||
r.addEventListener("success", new EventListener<Event>() {
|
||||
@Override
|
||||
public void handleEvent(Event evt) {
|
||||
cb.complete(BooleanResult._new(r.getResult() > 0));
|
||||
}
|
||||
});
|
||||
r.addEventListener("error", new EventListener<Event>() {
|
||||
@Override
|
||||
public void handleEvent(Event evt) {
|
||||
cb.complete(BooleanResult._new(false));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@JSBody(params = { "pat", "dat" }, script = "return { path: pat, data: dat };")
|
||||
protected static native JSObject writeRow(String name, ArrayBuffer data);
|
||||
|
||||
@Async
|
||||
protected static native BooleanResult writeWholeFile(IDBDatabase db, String name, ArrayBuffer data);
|
||||
|
||||
private static void writeWholeFile(IDBDatabase db, String name, ArrayBuffer data, final AsyncCallback<BooleanResult> cb) {
|
||||
IDBTransaction tx = db.transaction("filesystem", "readwrite");
|
||||
final IDBRequest r = tx.objectStore("filesystem").put(writeRow(name, data));
|
||||
|
||||
r.addEventListener("success", new EventListener<Event>() {
|
||||
@Override
|
||||
public void handleEvent(Event evt) {
|
||||
cb.complete(BooleanResult._new(true));
|
||||
}
|
||||
});
|
||||
r.addEventListener("error", new EventListener<Event>() {
|
||||
@Override
|
||||
public void handleEvent(Event evt) {
|
||||
cb.complete(BooleanResult._new(false));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static byte[] utf8(String str) {
|
||||
if(str == null) return null;
|
||||
return str.getBytes(Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
public static String utf8(byte[] str) {
|
||||
if(str == null) return null;
|
||||
return new String(str, Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
public static String CRLFtoLF(String str) {
|
||||
if(str == null) return null;
|
||||
return str.indexOf('\r') != -1 ? str.replace("\r", "") : str;
|
||||
}
|
||||
|
||||
public static String[] lines(String str) {
|
||||
if(str == null) return null;
|
||||
return CRLFtoLF(str).split("\n");
|
||||
}
|
||||
|
||||
}
|
1243
sp-server/src/main/java/net/minecraft/server/MinecraftServer.java
Normal file
1243
sp-server/src/main/java/net/minecraft/server/MinecraftServer.java
Normal file
File diff suppressed because it is too large
Load Diff
11
sp-server/src/main/java/net/minecraft/src/AABBLocalPool.java
Normal file
11
sp-server/src/main/java/net/minecraft/src/AABBLocalPool.java
Normal file
|
@ -0,0 +1,11 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
final class AABBLocalPool extends ThreadLocal {
|
||||
protected AABBPool createNewDefaultPool() {
|
||||
return new AABBPool(300, 2000);
|
||||
}
|
||||
|
||||
protected Object initialValue() {
|
||||
return this.createNewDefaultPool();
|
||||
}
|
||||
}
|
86
sp-server/src/main/java/net/minecraft/src/AABBPool.java
Normal file
86
sp-server/src/main/java/net/minecraft/src/AABBPool.java
Normal file
|
@ -0,0 +1,86 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AABBPool {
|
||||
/**
|
||||
* Maximum number of times the pool can be "cleaned" before the list is shrunk
|
||||
*/
|
||||
private final int maxNumCleans;
|
||||
|
||||
/**
|
||||
* Number of Pool entries to remove when cleanPool is called maxNumCleans times.
|
||||
*/
|
||||
private final int numEntriesToRemove;
|
||||
|
||||
/** List of AABB stored in this Pool */
|
||||
private final List listAABB = new ArrayList();
|
||||
|
||||
/** Next index to use when adding a Pool Entry. */
|
||||
private int nextPoolIndex = 0;
|
||||
|
||||
/**
|
||||
* Largest index reached by this Pool (can be reset to 0 upon calling cleanPool)
|
||||
*/
|
||||
private int maxPoolIndex = 0;
|
||||
|
||||
/** Number of times this Pool has been cleaned */
|
||||
private int numCleans = 0;
|
||||
|
||||
public AABBPool(int par1, int par2) {
|
||||
this.maxNumCleans = par1;
|
||||
this.numEntriesToRemove = par2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AABB, or reuses one that's no longer in use. Parameters: minX,
|
||||
* minY, minZ, maxX, maxY, maxZ. AABBs returned from this function should only
|
||||
* be used for one frame or tick, as after that they will be reused.
|
||||
*/
|
||||
public AxisAlignedBB getAABB(double par1, double par3, double par5, double par7, double par9, double par11) {
|
||||
AxisAlignedBB var13;
|
||||
|
||||
if (this.nextPoolIndex >= this.listAABB.size()) {
|
||||
var13 = new AxisAlignedBB(par1, par3, par5, par7, par9, par11);
|
||||
this.listAABB.add(var13);
|
||||
} else {
|
||||
var13 = (AxisAlignedBB) this.listAABB.get(this.nextPoolIndex);
|
||||
var13.setBounds(par1, par3, par5, par7, par9, par11);
|
||||
}
|
||||
|
||||
++this.nextPoolIndex;
|
||||
return var13;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the pool as "empty", starting over when adding new entries. If this is
|
||||
* called maxNumCleans times, the list size is reduced
|
||||
*/
|
||||
public void cleanPool() {
|
||||
if (this.nextPoolIndex > this.maxPoolIndex) {
|
||||
this.maxPoolIndex = this.nextPoolIndex;
|
||||
}
|
||||
|
||||
if (this.numCleans++ == this.maxNumCleans) {
|
||||
int var1 = Math.max(this.maxPoolIndex, this.listAABB.size() - this.numEntriesToRemove);
|
||||
|
||||
while (this.listAABB.size() > var1) {
|
||||
this.listAABB.remove(var1);
|
||||
}
|
||||
|
||||
this.maxPoolIndex = 0;
|
||||
this.numCleans = 0;
|
||||
}
|
||||
|
||||
this.nextPoolIndex = 0;
|
||||
}
|
||||
|
||||
public int getlistAABBsize() {
|
||||
return this.listAABB.size();
|
||||
}
|
||||
|
||||
public int getnextPoolIndex() {
|
||||
return this.nextPoolIndex;
|
||||
}
|
||||
}
|
116
sp-server/src/main/java/net/minecraft/src/Achievement.java
Normal file
116
sp-server/src/main/java/net/minecraft/src/Achievement.java
Normal file
|
@ -0,0 +1,116 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
public class Achievement extends StatBase {
|
||||
/**
|
||||
* Is the column (related to center of achievement gui, in 24 pixels unit) that
|
||||
* the achievement will be displayed.
|
||||
*/
|
||||
public final int displayColumn;
|
||||
|
||||
/**
|
||||
* Is the row (related to center of achievement gui, in 24 pixels unit) that the
|
||||
* achievement will be displayed.
|
||||
*/
|
||||
public final int displayRow;
|
||||
|
||||
/**
|
||||
* Holds the parent achievement, that must be taken before this achievement is
|
||||
* avaiable.
|
||||
*/
|
||||
public final Achievement parentAchievement;
|
||||
|
||||
/**
|
||||
* Holds the description of the achievement, ready to be formatted and/or
|
||||
* displayed.
|
||||
*/
|
||||
private final String achievementDescription;
|
||||
|
||||
/**
|
||||
* Holds the ItemStack that will be used to draw the achievement into the GUI.
|
||||
*/
|
||||
public final ItemStack theItemStack;
|
||||
|
||||
/**
|
||||
* Special achievements have a 'spiked' (on normal texture pack) frame, special
|
||||
* achievements are the hardest ones to achieve.
|
||||
*/
|
||||
private boolean isSpecial;
|
||||
|
||||
public Achievement(int par1, String par2Str, int par3, int par4, Item par5Item, Achievement par6Achievement) {
|
||||
this(par1, par2Str, par3, par4, new ItemStack(par5Item), par6Achievement);
|
||||
}
|
||||
|
||||
public Achievement(int par1, String par2Str, int par3, int par4, Block par5Block, Achievement par6Achievement) {
|
||||
this(par1, par2Str, par3, par4, new ItemStack(par5Block), par6Achievement);
|
||||
}
|
||||
|
||||
public Achievement(int par1, String par2Str, int par3, int par4, ItemStack par5ItemStack,
|
||||
Achievement par6Achievement) {
|
||||
super(5242880 + par1, "achievement." + par2Str);
|
||||
this.theItemStack = par5ItemStack;
|
||||
this.achievementDescription = "achievement." + par2Str + ".desc";
|
||||
this.displayColumn = par3;
|
||||
this.displayRow = par4;
|
||||
|
||||
if (par3 < AchievementList.minDisplayColumn) {
|
||||
AchievementList.minDisplayColumn = par3;
|
||||
}
|
||||
|
||||
if (par4 < AchievementList.minDisplayRow) {
|
||||
AchievementList.minDisplayRow = par4;
|
||||
}
|
||||
|
||||
if (par3 > AchievementList.maxDisplayColumn) {
|
||||
AchievementList.maxDisplayColumn = par3;
|
||||
}
|
||||
|
||||
if (par4 > AchievementList.maxDisplayRow) {
|
||||
AchievementList.maxDisplayRow = par4;
|
||||
}
|
||||
|
||||
this.parentAchievement = par6Achievement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not the given achievement or statistic is independent
|
||||
* (i.e., lacks prerequisites for being update).
|
||||
*/
|
||||
public Achievement setIndependent() {
|
||||
this.isIndependent = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special achievements have a 'spiked' (on normal texture pack) frame, special
|
||||
* achievements are the hardest ones to achieve.
|
||||
*/
|
||||
public Achievement setSpecial() {
|
||||
this.isSpecial = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the achievement on the internal list of registered achievements, also,
|
||||
* it's check for duplicated id's.
|
||||
*/
|
||||
public Achievement registerAchievement() {
|
||||
super.registerStat();
|
||||
AchievementList.achievementList.add(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the stat into StatList.
|
||||
*/
|
||||
public StatBase registerStat() {
|
||||
return this.registerAchievement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the current stat as independent (i.e., lacking prerequisites for
|
||||
* being updated) and returns the current instance.
|
||||
*/
|
||||
public StatBase initIndependentStat() {
|
||||
return this.setIndependent();
|
||||
}
|
||||
}
|
137
sp-server/src/main/java/net/minecraft/src/AchievementList.java
Normal file
137
sp-server/src/main/java/net/minecraft/src/AchievementList.java
Normal file
|
@ -0,0 +1,137 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AchievementList {
|
||||
/** Is the smallest column used to display a achievement on the GUI. */
|
||||
public static int minDisplayColumn;
|
||||
|
||||
/** Is the smallest row used to display a achievement on the GUI. */
|
||||
public static int minDisplayRow;
|
||||
|
||||
/** Is the biggest column used to display a achievement on the GUI. */
|
||||
public static int maxDisplayColumn;
|
||||
|
||||
/** Is the biggest row used to display a achievement on the GUI. */
|
||||
public static int maxDisplayRow;
|
||||
|
||||
/** The list holding all achievements */
|
||||
public static List achievementList = new ArrayList();
|
||||
|
||||
/** Is the 'open inventory' achievement. */
|
||||
public static Achievement openInventory = (new Achievement(0, "openInventory", 0, 0, Item.book, (Achievement) null))
|
||||
.setIndependent().registerAchievement();
|
||||
|
||||
/** Is the 'getting wood' achievement. */
|
||||
public static Achievement mineWood = (new Achievement(1, "mineWood", 2, 1, Block.wood, openInventory))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'benchmarking' achievement. */
|
||||
public static Achievement buildWorkBench = (new Achievement(2, "buildWorkBench", 4, -1, Block.workbench, mineWood))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'time to mine' achievement. */
|
||||
public static Achievement buildPickaxe = (new Achievement(3, "buildPickaxe", 4, 2, Item.pickaxeWood,
|
||||
buildWorkBench)).registerAchievement();
|
||||
|
||||
/** Is the 'hot topic' achievement. */
|
||||
public static Achievement buildFurnace = (new Achievement(4, "buildFurnace", 3, 4, Block.furnaceIdle, buildPickaxe))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'acquire hardware' achievement. */
|
||||
public static Achievement acquireIron = (new Achievement(5, "acquireIron", 1, 4, Item.ingotIron, buildFurnace))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'time to farm' achievement. */
|
||||
public static Achievement buildHoe = (new Achievement(6, "buildHoe", 2, -3, Item.hoeWood, buildWorkBench))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'bake bread' achievement. */
|
||||
public static Achievement makeBread = (new Achievement(7, "makeBread", -1, -3, Item.bread, buildHoe))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'the lie' achievement. */
|
||||
public static Achievement bakeCake = (new Achievement(8, "bakeCake", 0, -5, Item.cake, buildHoe))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'getting a upgrade' achievement. */
|
||||
public static Achievement buildBetterPickaxe = (new Achievement(9, "buildBetterPickaxe", 6, 2, Item.pickaxeStone,
|
||||
buildPickaxe)).registerAchievement();
|
||||
|
||||
/** Is the 'delicious fish' achievement. */
|
||||
public static Achievement cookFish = (new Achievement(10, "cookFish", 2, 6, Item.fishCooked, buildFurnace))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'on a rail' achievement */
|
||||
public static Achievement onARail = (new Achievement(11, "onARail", 2, 3, Block.rail, acquireIron)).setSpecial()
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'time to strike' achievement. */
|
||||
public static Achievement buildSword = (new Achievement(12, "buildSword", 6, -1, Item.swordWood, buildWorkBench))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'monster hunter' achievement. */
|
||||
public static Achievement killEnemy = (new Achievement(13, "killEnemy", 8, -1, Item.bone, buildSword))
|
||||
.registerAchievement();
|
||||
|
||||
/** is the 'cow tipper' achievement. */
|
||||
public static Achievement killCow = (new Achievement(14, "killCow", 7, -3, Item.leather, buildSword))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'when pig fly' achievement. */
|
||||
public static Achievement flyPig = (new Achievement(15, "flyPig", 8, -4, Item.saddle, killCow)).setSpecial()
|
||||
.registerAchievement();
|
||||
|
||||
/** The achievement for killing a Skeleton from 50 meters aways. */
|
||||
public static Achievement snipeSkeleton = (new Achievement(16, "snipeSkeleton", 7, 0, Item.bow, killEnemy))
|
||||
.setSpecial().registerAchievement();
|
||||
|
||||
/** Is the 'DIAMONDS!' achievement */
|
||||
public static Achievement diamonds = (new Achievement(17, "diamonds", -1, 5, Item.diamond, acquireIron))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'We Need to Go Deeper' achievement */
|
||||
public static Achievement portal = (new Achievement(18, "portal", -1, 7, Block.obsidian, diamonds))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'Return to Sender' achievement */
|
||||
public static Achievement ghast = (new Achievement(19, "ghast", -4, 8, Item.ghastTear, portal)).setSpecial()
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'Into Fire' achievement */
|
||||
public static Achievement blazeRod = (new Achievement(20, "blazeRod", 0, 9, Item.blazeRod, portal))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'Local Brewery' achievement */
|
||||
public static Achievement potion = (new Achievement(21, "potion", 2, 8, Item.potion, blazeRod))
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'The End?' achievement */
|
||||
public static Achievement theEnd = (new Achievement(22, "theEnd", 3, 10, Item.eyeOfEnder, blazeRod)).setSpecial()
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'The End.' achievement */
|
||||
public static Achievement theEnd2 = (new Achievement(23, "theEnd2", 4, 13, Block.dragonEgg, theEnd)).setSpecial()
|
||||
.registerAchievement();
|
||||
|
||||
/** Is the 'Enchanter' achievement */
|
||||
public static Achievement enchantments = (new Achievement(24, "enchantments", -4, 4, Block.enchantmentTable,
|
||||
diamonds)).registerAchievement();
|
||||
public static Achievement overkill = (new Achievement(25, "overkill", -4, 1, Item.swordDiamond, enchantments))
|
||||
.setSpecial().registerAchievement();
|
||||
|
||||
/** Is the 'Librarian' achievement */
|
||||
public static Achievement bookcase = (new Achievement(26, "bookcase", -3, 6, Block.bookShelf, enchantments))
|
||||
.registerAchievement();
|
||||
|
||||
/**
|
||||
* A stub functions called to make the static initializer for this class run.
|
||||
*/
|
||||
public static void init() {
|
||||
}
|
||||
|
||||
static {
|
||||
System.out.println(achievementList.size() + " achievements");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AchievementMap {
|
||||
/** Holds the singleton instance of AchievementMap. */
|
||||
public static AchievementMap instance = new AchievementMap();
|
||||
|
||||
/** Maps a achievement id with it's unique GUID. */
|
||||
private Map guidMap = new HashMap();
|
||||
|
||||
private AchievementMap() {
|
||||
try {
|
||||
BufferedReader var1 = new BufferedReader(
|
||||
new InputStreamReader(AchievementMap.class.getResourceAsStream("/achievement/map.txt")));
|
||||
String var2;
|
||||
|
||||
while ((var2 = var1.readLine()) != null) {
|
||||
String[] var3 = var2.split(",");
|
||||
int var4 = Integer.parseInt(var3[0]);
|
||||
this.guidMap.put(Integer.valueOf(var4), var3[1]);
|
||||
}
|
||||
|
||||
var1.close();
|
||||
} catch (Exception var5) {
|
||||
var5.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique GUID of a achievement id.
|
||||
*/
|
||||
public static String getGuid(int par0) {
|
||||
return (String) instance.guidMap.get(Integer.valueOf(par0));
|
||||
}
|
||||
}
|
371
sp-server/src/main/java/net/minecraft/src/AnvilChunkLoader.java
Normal file
371
sp-server/src/main/java/net/minecraft/src/AnvilChunkLoader.java
Normal file
|
@ -0,0 +1,371 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class AnvilChunkLoader implements IChunkLoader, IThreadedFileIO {
|
||||
private List chunksToRemove = new ArrayList();
|
||||
private Set pendingAnvilChunksCoordinates = new HashSet();
|
||||
private Object syncLockObject = new Object();
|
||||
|
||||
/** Save directory for chunks using the Anvil format */
|
||||
private final File chunkSaveLocation;
|
||||
|
||||
public AnvilChunkLoader(File par1File) {
|
||||
this.chunkSaveLocation = par1File;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the specified(XZ) chunk into the specified world.
|
||||
*/
|
||||
public Chunk loadChunk(World par1World, int par2, int par3) throws IOException {
|
||||
NBTTagCompound var4 = null;
|
||||
ChunkCoordIntPair var5 = new ChunkCoordIntPair(par2, par3);
|
||||
Object var6 = this.syncLockObject;
|
||||
|
||||
synchronized (this.syncLockObject) {
|
||||
if (this.pendingAnvilChunksCoordinates.contains(var5)) {
|
||||
for (int var7 = 0; var7 < this.chunksToRemove.size(); ++var7) {
|
||||
if (((AnvilChunkLoaderPending) this.chunksToRemove.get(var7)).chunkCoordinate.equals(var5)) {
|
||||
var4 = ((AnvilChunkLoaderPending) this.chunksToRemove.get(var7)).nbtTags;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (var4 == null) {
|
||||
DataInputStream var10 = RegionFileCache.getChunkInputStream(this.chunkSaveLocation, par2, par3);
|
||||
|
||||
if (var10 == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var4 = CompressedStreamTools.read(var10);
|
||||
}
|
||||
|
||||
return this.checkedReadChunkFromNBT(par1World, par2, par3, var4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps readChunkFromNBT. Checks the coordinates and several NBT tags.
|
||||
*/
|
||||
protected Chunk checkedReadChunkFromNBT(World par1World, int par2, int par3, NBTTagCompound par4NBTTagCompound) {
|
||||
if (!par4NBTTagCompound.hasKey("Level")) {
|
||||
par1World.getWorldLogAgent()
|
||||
.logSevere("Chunk file at " + par2 + "," + par3 + " is missing level data, skipping");
|
||||
return null;
|
||||
} else if (!par4NBTTagCompound.getCompoundTag("Level").hasKey("Sections")) {
|
||||
par1World.getWorldLogAgent()
|
||||
.logSevere("Chunk file at " + par2 + "," + par3 + " is missing block data, skipping");
|
||||
return null;
|
||||
} else {
|
||||
Chunk var5 = this.readChunkFromNBT(par1World, par4NBTTagCompound.getCompoundTag("Level"));
|
||||
|
||||
if (!var5.isAtLocation(par2, par3)) {
|
||||
par1World.getWorldLogAgent()
|
||||
.logSevere("Chunk file at " + par2 + "," + par3
|
||||
+ " is in the wrong location; relocating. (Expected " + par2 + ", " + par3 + ", got "
|
||||
+ var5.xPosition + ", " + var5.zPosition + ")");
|
||||
par4NBTTagCompound.setInteger("xPos", par2);
|
||||
par4NBTTagCompound.setInteger("zPos", par3);
|
||||
var5 = this.readChunkFromNBT(par1World, par4NBTTagCompound.getCompoundTag("Level"));
|
||||
}
|
||||
|
||||
return var5;
|
||||
}
|
||||
}
|
||||
|
||||
public void saveChunk(World par1World, Chunk par2Chunk) throws MinecraftException, IOException {
|
||||
par1World.checkSessionLock();
|
||||
|
||||
try {
|
||||
NBTTagCompound var3 = new NBTTagCompound();
|
||||
NBTTagCompound var4 = new NBTTagCompound();
|
||||
var3.setTag("Level", var4);
|
||||
this.writeChunkToNBT(par2Chunk, par1World, var4);
|
||||
this.addChunkToPending(par2Chunk.getChunkCoordIntPair(), var3);
|
||||
} catch (Exception var5) {
|
||||
var5.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected void addChunkToPending(ChunkCoordIntPair par1ChunkCoordIntPair, NBTTagCompound par2NBTTagCompound) {
|
||||
Object var3 = this.syncLockObject;
|
||||
|
||||
synchronized (this.syncLockObject) {
|
||||
if (this.pendingAnvilChunksCoordinates.contains(par1ChunkCoordIntPair)) {
|
||||
for (int var4 = 0; var4 < this.chunksToRemove.size(); ++var4) {
|
||||
if (((AnvilChunkLoaderPending) this.chunksToRemove.get(var4)).chunkCoordinate
|
||||
.equals(par1ChunkCoordIntPair)) {
|
||||
this.chunksToRemove.set(var4,
|
||||
new AnvilChunkLoaderPending(par1ChunkCoordIntPair, par2NBTTagCompound));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.chunksToRemove.add(new AnvilChunkLoaderPending(par1ChunkCoordIntPair, par2NBTTagCompound));
|
||||
this.pendingAnvilChunksCoordinates.add(par1ChunkCoordIntPair);
|
||||
ThreadedFileIOBase.threadedIOInstance.queueIO(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean stating if the write was unsuccessful.
|
||||
*/
|
||||
public boolean writeNextIO() {
|
||||
AnvilChunkLoaderPending var1 = null;
|
||||
Object var2 = this.syncLockObject;
|
||||
|
||||
synchronized (this.syncLockObject) {
|
||||
if (this.chunksToRemove.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var1 = (AnvilChunkLoaderPending) this.chunksToRemove.remove(0);
|
||||
this.pendingAnvilChunksCoordinates.remove(var1.chunkCoordinate);
|
||||
}
|
||||
|
||||
if (var1 != null) {
|
||||
try {
|
||||
this.writeChunkNBTTags(var1);
|
||||
} catch (Exception var4) {
|
||||
var4.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void writeChunkNBTTags(AnvilChunkLoaderPending par1AnvilChunkLoaderPending) throws IOException {
|
||||
DataOutputStream var2 = RegionFileCache.getChunkOutputStream(this.chunkSaveLocation,
|
||||
par1AnvilChunkLoaderPending.chunkCoordinate.chunkXPos,
|
||||
par1AnvilChunkLoaderPending.chunkCoordinate.chunkZPos);
|
||||
CompressedStreamTools.write(par1AnvilChunkLoaderPending.nbtTags, var2);
|
||||
var2.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save extra data associated with this Chunk not normally saved during
|
||||
* autosave, only during chunk unload. Currently unused.
|
||||
*/
|
||||
public void saveExtraChunkData(World par1World, Chunk par2Chunk) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every World.tick()
|
||||
*/
|
||||
public void chunkTick() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save extra data not associated with any Chunk. Not saved during autosave,
|
||||
* only during world unload. Currently unused.
|
||||
*/
|
||||
public void saveExtraData() {
|
||||
while (this.writeNextIO()) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the Chunk passed as an argument to the NBTTagCompound also passed,
|
||||
* using the World argument to retrieve the Chunk's last update time.
|
||||
*/
|
||||
private void writeChunkToNBT(Chunk par1Chunk, World par2World, NBTTagCompound par3NBTTagCompound) {
|
||||
par3NBTTagCompound.setInteger("xPos", par1Chunk.xPosition);
|
||||
par3NBTTagCompound.setInteger("zPos", par1Chunk.zPosition);
|
||||
par3NBTTagCompound.setLong("LastUpdate", par2World.getTotalWorldTime());
|
||||
par3NBTTagCompound.setIntArray("HeightMap", par1Chunk.heightMap);
|
||||
par3NBTTagCompound.setBoolean("TerrainPopulated", par1Chunk.isTerrainPopulated);
|
||||
ExtendedBlockStorage[] var4 = par1Chunk.getBlockStorageArray();
|
||||
NBTTagList var5 = new NBTTagList("Sections");
|
||||
boolean var6 = !par2World.provider.hasNoSky;
|
||||
ExtendedBlockStorage[] var7 = var4;
|
||||
int var8 = var4.length;
|
||||
NBTTagCompound var11;
|
||||
|
||||
for (int var9 = 0; var9 < var8; ++var9) {
|
||||
ExtendedBlockStorage var10 = var7[var9];
|
||||
|
||||
if (var10 != null) {
|
||||
var11 = new NBTTagCompound();
|
||||
var11.setByte("Y", (byte) (var10.getYLocation() >> 4 & 255));
|
||||
var11.setByteArray("Blocks", var10.getBlockLSBArray());
|
||||
|
||||
if (var10.getBlockMSBArray() != null) {
|
||||
var11.setByteArray("Add", var10.getBlockMSBArray().data);
|
||||
}
|
||||
|
||||
var11.setByteArray("Data", var10.getMetadataArray().data);
|
||||
var11.setByteArray("BlockLight", var10.getBlocklightArray().data);
|
||||
|
||||
if (var6) {
|
||||
var11.setByteArray("SkyLight", var10.getSkylightArray().data);
|
||||
} else {
|
||||
var11.setByteArray("SkyLight", new byte[var10.getBlocklightArray().data.length]);
|
||||
}
|
||||
|
||||
var5.appendTag(var11);
|
||||
}
|
||||
}
|
||||
|
||||
par3NBTTagCompound.setTag("Sections", var5);
|
||||
par3NBTTagCompound.setByteArray("Biomes", par1Chunk.getBiomeArray());
|
||||
par1Chunk.hasEntities = false;
|
||||
NBTTagList var16 = new NBTTagList();
|
||||
Iterator var18;
|
||||
|
||||
for (var8 = 0; var8 < par1Chunk.entityLists.length; ++var8) {
|
||||
var18 = par1Chunk.entityLists[var8].iterator();
|
||||
|
||||
while (var18.hasNext()) {
|
||||
Entity var20 = (Entity) var18.next();
|
||||
var11 = new NBTTagCompound();
|
||||
|
||||
if (var20.addEntityID(var11)) {
|
||||
par1Chunk.hasEntities = true;
|
||||
var16.appendTag(var11);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
par3NBTTagCompound.setTag("Entities", var16);
|
||||
NBTTagList var17 = new NBTTagList();
|
||||
var18 = par1Chunk.chunkTileEntityMap.values().iterator();
|
||||
|
||||
while (var18.hasNext()) {
|
||||
TileEntity var21 = (TileEntity) var18.next();
|
||||
var11 = new NBTTagCompound();
|
||||
var21.writeToNBT(var11);
|
||||
var17.appendTag(var11);
|
||||
}
|
||||
|
||||
par3NBTTagCompound.setTag("TileEntities", var17);
|
||||
List var19 = par2World.getPendingBlockUpdates(par1Chunk, false);
|
||||
|
||||
if (var19 != null) {
|
||||
long var22 = par2World.getTotalWorldTime();
|
||||
NBTTagList var12 = new NBTTagList();
|
||||
Iterator var13 = var19.iterator();
|
||||
|
||||
while (var13.hasNext()) {
|
||||
NextTickListEntry var14 = (NextTickListEntry) var13.next();
|
||||
NBTTagCompound var15 = new NBTTagCompound();
|
||||
var15.setInteger("i", var14.blockID);
|
||||
var15.setInteger("x", var14.xCoord);
|
||||
var15.setInteger("y", var14.yCoord);
|
||||
var15.setInteger("z", var14.zCoord);
|
||||
var15.setInteger("t", (int) (var14.scheduledTime - var22));
|
||||
var15.setInteger("p", var14.field_82754_f);
|
||||
var12.appendTag(var15);
|
||||
}
|
||||
|
||||
par3NBTTagCompound.setTag("TileTicks", var12);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the data stored in the passed NBTTagCompound and creates a Chunk with
|
||||
* that data in the passed World. Returns the created Chunk.
|
||||
*/
|
||||
private Chunk readChunkFromNBT(World par1World, NBTTagCompound par2NBTTagCompound) {
|
||||
int var3 = par2NBTTagCompound.getInteger("xPos");
|
||||
int var4 = par2NBTTagCompound.getInteger("zPos");
|
||||
Chunk var5 = new Chunk(par1World, var3, var4);
|
||||
var5.heightMap = par2NBTTagCompound.getIntArray("HeightMap");
|
||||
var5.isTerrainPopulated = par2NBTTagCompound.getBoolean("TerrainPopulated");
|
||||
NBTTagList var6 = par2NBTTagCompound.getTagList("Sections");
|
||||
byte var7 = 16;
|
||||
ExtendedBlockStorage[] var8 = new ExtendedBlockStorage[var7];
|
||||
boolean var9 = !par1World.provider.hasNoSky;
|
||||
|
||||
for (int var10 = 0; var10 < var6.tagCount(); ++var10) {
|
||||
NBTTagCompound var11 = (NBTTagCompound) var6.tagAt(var10);
|
||||
byte var12 = var11.getByte("Y");
|
||||
ExtendedBlockStorage var13 = new ExtendedBlockStorage(var12 << 4, var9);
|
||||
var13.setBlockLSBArray(var11.getByteArray("Blocks"));
|
||||
|
||||
if (var11.hasKey("Add")) {
|
||||
var13.setBlockMSBArray(new NibbleArray(var11.getByteArray("Add"), 4));
|
||||
}
|
||||
|
||||
var13.setBlockMetadataArray(new NibbleArray(var11.getByteArray("Data"), 4));
|
||||
var13.setBlocklightArray(new NibbleArray(var11.getByteArray("BlockLight"), 4));
|
||||
|
||||
if (var9) {
|
||||
var13.setSkylightArray(new NibbleArray(var11.getByteArray("SkyLight"), 4));
|
||||
}
|
||||
|
||||
var13.removeInvalidBlocks();
|
||||
var8[var12] = var13;
|
||||
}
|
||||
|
||||
var5.setStorageArrays(var8);
|
||||
|
||||
if (par2NBTTagCompound.hasKey("Biomes")) {
|
||||
var5.setBiomeArray(par2NBTTagCompound.getByteArray("Biomes"));
|
||||
}
|
||||
|
||||
NBTTagList var17 = par2NBTTagCompound.getTagList("Entities");
|
||||
|
||||
if (var17 != null) {
|
||||
for (int var18 = 0; var18 < var17.tagCount(); ++var18) {
|
||||
NBTTagCompound var20 = (NBTTagCompound) var17.tagAt(var18);
|
||||
Entity var22 = EntityList.createEntityFromNBT(var20, par1World);
|
||||
var5.hasEntities = true;
|
||||
|
||||
if (var22 != null) {
|
||||
var5.addEntity(var22);
|
||||
Entity var14 = var22;
|
||||
|
||||
for (NBTTagCompound var15 = var20; var15.hasKey("Riding"); var15 = var15.getCompoundTag("Riding")) {
|
||||
Entity var16 = EntityList.createEntityFromNBT(var15.getCompoundTag("Riding"), par1World);
|
||||
|
||||
if (var16 != null) {
|
||||
var5.addEntity(var16);
|
||||
var14.mountEntity(var16);
|
||||
}
|
||||
|
||||
var14 = var16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NBTTagList var19 = par2NBTTagCompound.getTagList("TileEntities");
|
||||
|
||||
if (var19 != null) {
|
||||
for (int var21 = 0; var21 < var19.tagCount(); ++var21) {
|
||||
NBTTagCompound var24 = (NBTTagCompound) var19.tagAt(var21);
|
||||
TileEntity var26 = TileEntity.createAndLoadEntity(var24);
|
||||
|
||||
if (var26 != null) {
|
||||
var5.addTileEntity(var26);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (par2NBTTagCompound.hasKey("TileTicks")) {
|
||||
NBTTagList var23 = par2NBTTagCompound.getTagList("TileTicks");
|
||||
|
||||
if (var23 != null) {
|
||||
for (int var25 = 0; var25 < var23.tagCount(); ++var25) {
|
||||
NBTTagCompound var27 = (NBTTagCompound) var23.tagAt(var25);
|
||||
par1World.scheduleBlockUpdateFromLoad(var27.getInteger("x"), var27.getInteger("y"),
|
||||
var27.getInteger("z"), var27.getInteger("i"), var27.getInteger("t"), var27.getInteger("p"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return var5;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
class AnvilChunkLoaderPending {
|
||||
public final ChunkCoordIntPair chunkCoordinate;
|
||||
public final NBTTagCompound nbtTags;
|
||||
|
||||
public AnvilChunkLoaderPending(ChunkCoordIntPair par1ChunkCoordIntPair, NBTTagCompound par2NBTTagCompound) {
|
||||
this.chunkCoordinate = par1ChunkCoordIntPair;
|
||||
this.nbtTags = par2NBTTagCompound;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
public class AnvilConverterData {
|
||||
public long lastUpdated;
|
||||
public boolean terrainPopulated;
|
||||
public byte[] heightmap;
|
||||
public NibbleArrayReader blockLight;
|
||||
public NibbleArrayReader skyLight;
|
||||
public NibbleArrayReader data;
|
||||
public byte[] blocks;
|
||||
public NBTTagList entities;
|
||||
public NBTTagList tileEntities;
|
||||
public NBTTagList tileTicks;
|
||||
public final int x;
|
||||
public final int z;
|
||||
|
||||
public AnvilConverterData(int par1, int par2) {
|
||||
this.x = par1;
|
||||
this.z = par2;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class AnvilSaveConverter extends SaveFormatOld {
|
||||
public AnvilSaveConverter(File par1File) {
|
||||
super(par1File);
|
||||
}
|
||||
|
||||
protected int getSaveVersion() {
|
||||
return 19133;
|
||||
}
|
||||
|
||||
public void flushCache() {
|
||||
RegionFileCache.clearRegionFileReferences();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns back a loader for the specified save directory
|
||||
*/
|
||||
public ISaveHandler getSaveLoader(String par1Str, boolean par2) {
|
||||
return new AnvilSaveHandler(this.savesDirectory, par1Str, par2);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets if the map is old chunk saving (true) or McRegion (false)
|
||||
*/
|
||||
public boolean isOldMapFormat(String par1Str) {
|
||||
WorldInfo var2 = this.getWorldInfo(par1Str);
|
||||
return var2 != null && var2.getSaveVersion() != this.getSaveVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* converts the map to mcRegion
|
||||
*/
|
||||
public boolean convertMapFormat(String par1Str, IProgressUpdate par2IProgressUpdate) {
|
||||
par2IProgressUpdate.setLoadingProgress(0);
|
||||
ArrayList var3 = new ArrayList();
|
||||
ArrayList var4 = new ArrayList();
|
||||
ArrayList var5 = new ArrayList();
|
||||
File var6 = new File(this.savesDirectory, par1Str);
|
||||
File var7 = new File(var6, "DIM-1");
|
||||
File var8 = new File(var6, "DIM1");
|
||||
MinecraftServer.getServer().getLogAgent().func_98233_a("Scanning folders...");
|
||||
this.addRegionFilesToCollection(var6, var3);
|
||||
|
||||
if (var7.exists()) {
|
||||
this.addRegionFilesToCollection(var7, var4);
|
||||
}
|
||||
|
||||
if (var8.exists()) {
|
||||
this.addRegionFilesToCollection(var8, var5);
|
||||
}
|
||||
|
||||
int var9 = var3.size() + var4.size() + var5.size();
|
||||
MinecraftServer.getServer().getLogAgent().func_98233_a("Total conversion count is " + var9);
|
||||
WorldInfo var10 = this.getWorldInfo(par1Str);
|
||||
Object var11 = null;
|
||||
|
||||
if (var10.getTerrainType() == WorldType.FLAT) {
|
||||
var11 = new WorldChunkManagerHell(BiomeGenBase.plains, 0.5F, 0.5F);
|
||||
} else {
|
||||
var11 = new WorldChunkManager(var10.getSeed(), var10.getTerrainType());
|
||||
}
|
||||
|
||||
this.convertFile(new File(var6, "region"), var3, (WorldChunkManager) var11, 0, var9, par2IProgressUpdate);
|
||||
this.convertFile(new File(var7, "region"), var4, new WorldChunkManagerHell(BiomeGenBase.hell, 1.0F, 0.0F),
|
||||
var3.size(), var9, par2IProgressUpdate);
|
||||
this.convertFile(new File(var8, "region"), var5, new WorldChunkManagerHell(BiomeGenBase.sky, 0.5F, 0.0F),
|
||||
var3.size() + var4.size(), var9, par2IProgressUpdate);
|
||||
var10.setSaveVersion(19133);
|
||||
|
||||
if (var10.getTerrainType() == WorldType.DEFAULT_1_1) {
|
||||
var10.setTerrainType(WorldType.DEFAULT);
|
||||
}
|
||||
|
||||
this.createFile(par1Str);
|
||||
ISaveHandler var12 = this.getSaveLoader(par1Str, false);
|
||||
var12.saveWorldInfo(var10);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* par: filename for the level.dat_mcr backup
|
||||
*/
|
||||
private void createFile(String par1Str) {
|
||||
File var2 = new File(this.savesDirectory, par1Str);
|
||||
|
||||
if (!var2.exists()) {
|
||||
System.out.println("Warning: Unable to create level.dat_mcr backup");
|
||||
} else {
|
||||
File var3 = new File(var2, "level.dat");
|
||||
|
||||
if (!var3.exists()) {
|
||||
System.out.println("Warning: Unable to create level.dat_mcr backup");
|
||||
} else {
|
||||
File var4 = new File(var2, "level.dat_mcr");
|
||||
|
||||
if (!var3.renameTo(var4)) {
|
||||
System.out.println("Warning: Unable to create level.dat_mcr backup");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void convertFile(File par1File, Iterable par2Iterable, WorldChunkManager par3WorldChunkManager, int par4,
|
||||
int par5, IProgressUpdate par6IProgressUpdate) {
|
||||
Iterator var7 = par2Iterable.iterator();
|
||||
|
||||
while (var7.hasNext()) {
|
||||
File var8 = (File) var7.next();
|
||||
this.convertChunks(par1File, var8, par3WorldChunkManager, par4, par5, par6IProgressUpdate);
|
||||
++par4;
|
||||
int var9 = (int) Math.round(100.0D * (double) par4 / (double) par5);
|
||||
par6IProgressUpdate.setLoadingProgress(var9);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* copies a 32x32 chunk set from par2File to par1File, via AnvilConverterData
|
||||
*/
|
||||
private void convertChunks(File par1File, File par2File, WorldChunkManager par3WorldChunkManager, int par4,
|
||||
int par5, IProgressUpdate par6IProgressUpdate) {
|
||||
try {
|
||||
String var7 = par2File.getName();
|
||||
RegionFile var8 = new RegionFile(par2File);
|
||||
RegionFile var9 = new RegionFile(
|
||||
new File(par1File, var7.substring(0, var7.length() - ".mcr".length()) + ".mca"));
|
||||
|
||||
for (int var10 = 0; var10 < 32; ++var10) {
|
||||
int var11;
|
||||
|
||||
for (var11 = 0; var11 < 32; ++var11) {
|
||||
if (var8.isChunkSaved(var10, var11) && !var9.isChunkSaved(var10, var11)) {
|
||||
DataInputStream var12 = var8.getChunkDataInputStream(var10, var11);
|
||||
|
||||
if (var12 == null) {
|
||||
MinecraftServer.getServer().getLogAgent().func_98236_b("Failed to fetch input stream");
|
||||
} else {
|
||||
NBTTagCompound var13 = CompressedStreamTools.read(var12);
|
||||
var12.close();
|
||||
NBTTagCompound var14 = var13.getCompoundTag("Level");
|
||||
AnvilConverterData var15 = ChunkLoader.load(var14);
|
||||
NBTTagCompound var16 = new NBTTagCompound();
|
||||
NBTTagCompound var17 = new NBTTagCompound();
|
||||
var16.setTag("Level", var17);
|
||||
ChunkLoader.convertToAnvilFormat(var15, var17, par3WorldChunkManager);
|
||||
DataOutputStream var18 = var9.getChunkDataOutputStream(var10, var11);
|
||||
CompressedStreamTools.write(var16, var18);
|
||||
var18.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var11 = (int) Math.round(100.0D * (double) (par4 * 1024) / (double) (par5 * 1024));
|
||||
int var20 = (int) Math
|
||||
.round(100.0D * (double) ((var10 + 1) * 32 + par4 * 1024) / (double) (par5 * 1024));
|
||||
|
||||
if (var20 > var11) {
|
||||
par6IProgressUpdate.setLoadingProgress(var20);
|
||||
}
|
||||
}
|
||||
|
||||
var8.close();
|
||||
var9.close();
|
||||
} catch (IOException var19) {
|
||||
var19.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* filters the files in the par1 directory, and adds them to the par2
|
||||
* collections
|
||||
*/
|
||||
private void addRegionFilesToCollection(File par1File, Collection par2Collection) {
|
||||
File var3 = new File(par1File, "region");
|
||||
File[] var4 = var3.listFiles(new AnvilSaveConverterFileFilter(this));
|
||||
|
||||
if (var4 != null) {
|
||||
Collections.addAll(par2Collection, var4);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
|
||||
class AnvilSaveConverterFileFilter implements FilenameFilter {
|
||||
final AnvilSaveConverter parent;
|
||||
|
||||
AnvilSaveConverterFileFilter(AnvilSaveConverter par1AnvilSaveConverter) {
|
||||
this.parent = par1AnvilSaveConverter;
|
||||
}
|
||||
|
||||
public boolean accept(File par1File, String par2Str) {
|
||||
return par2Str.endsWith(".mcr");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class AnvilSaveHandler extends SaveHandler {
|
||||
public AnvilSaveHandler(File par1File, String par2Str, boolean par3) {
|
||||
super(par1File, par2Str, par3);
|
||||
}
|
||||
|
||||
/**
|
||||
* initializes and returns the chunk loader for the specified world provider
|
||||
*/
|
||||
public IChunkLoader getChunkLoader(WorldProvider par1WorldProvider) {
|
||||
File var2 = this.getWorldDirectory();
|
||||
File var3;
|
||||
|
||||
if (par1WorldProvider instanceof WorldProviderHell) {
|
||||
var3 = new File(var2, "DIM-1");
|
||||
var3.mkdirs();
|
||||
return new AnvilChunkLoader(var3);
|
||||
} else if (par1WorldProvider instanceof WorldProviderEnd) {
|
||||
var3 = new File(var2, "DIM1");
|
||||
var3.mkdirs();
|
||||
return new AnvilChunkLoader(var3);
|
||||
} else {
|
||||
return new AnvilChunkLoader(var2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the given World Info with the given NBTTagCompound as the Player.
|
||||
*/
|
||||
public void saveWorldInfoWithPlayer(WorldInfo par1WorldInfo, NBTTagCompound par2NBTTagCompound) {
|
||||
par1WorldInfo.setSaveVersion(19133);
|
||||
super.saveWorldInfoWithPlayer(par1WorldInfo, par2NBTTagCompound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to flush all changes to disk, waiting for them to complete.
|
||||
*/
|
||||
public void flush() {
|
||||
try {
|
||||
ThreadedFileIOBase.threadedIOInstance.waitForFinish();
|
||||
} catch (InterruptedException var2) {
|
||||
var2.printStackTrace();
|
||||
}
|
||||
|
||||
RegionFileCache.clearRegionFileReferences();
|
||||
}
|
||||
}
|
425
sp-server/src/main/java/net/minecraft/src/AxisAlignedBB.java
Normal file
425
sp-server/src/main/java/net/minecraft/src/AxisAlignedBB.java
Normal file
|
@ -0,0 +1,425 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
public class AxisAlignedBB {
|
||||
/** ThreadLocal AABBPool */
|
||||
private static final ThreadLocal theAABBLocalPool = new AABBLocalPool();
|
||||
public double minX;
|
||||
public double minY;
|
||||
public double minZ;
|
||||
public double maxX;
|
||||
public double maxY;
|
||||
public double maxZ;
|
||||
|
||||
/**
|
||||
* Returns a bounding box with the specified bounds. Args: minX, minY, minZ,
|
||||
* maxX, maxY, maxZ
|
||||
*/
|
||||
public static AxisAlignedBB getBoundingBox(double par0, double par2, double par4, double par6, double par8,
|
||||
double par10) {
|
||||
return new AxisAlignedBB(par0, par2, par4, par6, par8, par10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ThreadLocal AABBPool
|
||||
*/
|
||||
public static AABBPool getAABBPool() {
|
||||
return (AABBPool) theAABBLocalPool.get();
|
||||
}
|
||||
|
||||
protected AxisAlignedBB(double par1, double par3, double par5, double par7, double par9, double par11) {
|
||||
this.minX = par1;
|
||||
this.minY = par3;
|
||||
this.minZ = par5;
|
||||
this.maxX = par7;
|
||||
this.maxY = par9;
|
||||
this.maxZ = par11;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bounds of the bounding box. Args: minX, minY, minZ, maxX, maxY, maxZ
|
||||
*/
|
||||
public AxisAlignedBB setBounds(double par1, double par3, double par5, double par7, double par9, double par11) {
|
||||
this.minX = par1;
|
||||
this.minY = par3;
|
||||
this.minZ = par5;
|
||||
this.maxX = par7;
|
||||
this.maxY = par9;
|
||||
this.maxZ = par11;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the coordinates to the bounding box extending it if the point lies
|
||||
* outside the current ranges. Args: x, y, z
|
||||
*/
|
||||
public AxisAlignedBB addCoord(double par1, double par3, double par5) {
|
||||
double var7 = this.minX;
|
||||
double var9 = this.minY;
|
||||
double var11 = this.minZ;
|
||||
double var13 = this.maxX;
|
||||
double var15 = this.maxY;
|
||||
double var17 = this.maxZ;
|
||||
|
||||
if (par1 < 0.0D) {
|
||||
var7 += par1;
|
||||
}
|
||||
|
||||
if (par1 > 0.0D) {
|
||||
var13 += par1;
|
||||
}
|
||||
|
||||
if (par3 < 0.0D) {
|
||||
var9 += par3;
|
||||
}
|
||||
|
||||
if (par3 > 0.0D) {
|
||||
var15 += par3;
|
||||
}
|
||||
|
||||
if (par5 < 0.0D) {
|
||||
var11 += par5;
|
||||
}
|
||||
|
||||
if (par5 > 0.0D) {
|
||||
var17 += par5;
|
||||
}
|
||||
|
||||
return getAABBPool().getAABB(var7, var9, var11, var13, var15, var17);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bounding box expanded by the specified vector (if negative numbers
|
||||
* are given it will shrink). Args: x, y, z
|
||||
*/
|
||||
public AxisAlignedBB expand(double par1, double par3, double par5) {
|
||||
double var7 = this.minX - par1;
|
||||
double var9 = this.minY - par3;
|
||||
double var11 = this.minZ - par5;
|
||||
double var13 = this.maxX + par1;
|
||||
double var15 = this.maxY + par3;
|
||||
double var17 = this.maxZ + par5;
|
||||
return getAABBPool().getAABB(var7, var9, var11, var13, var15, var17);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bounding box offseted by the specified vector (if negative numbers
|
||||
* are given it will shrink). Args: x, y, z
|
||||
*/
|
||||
public AxisAlignedBB getOffsetBoundingBox(double par1, double par3, double par5) {
|
||||
return getAABBPool().getAABB(this.minX + par1, this.minY + par3, this.minZ + par5, this.maxX + par1,
|
||||
this.maxY + par3, this.maxZ + par5);
|
||||
}
|
||||
|
||||
/**
|
||||
* if instance and the argument bounding boxes overlap in the Y and Z
|
||||
* dimensions, calculate the offset between them in the X dimension. return var2
|
||||
* if the bounding boxes do not overlap or if var2 is closer to 0 then the
|
||||
* calculated offset. Otherwise return the calculated offset.
|
||||
*/
|
||||
public double calculateXOffset(AxisAlignedBB par1AxisAlignedBB, double par2) {
|
||||
if (par1AxisAlignedBB.maxY > this.minY && par1AxisAlignedBB.minY < this.maxY) {
|
||||
if (par1AxisAlignedBB.maxZ > this.minZ && par1AxisAlignedBB.minZ < this.maxZ) {
|
||||
double var4;
|
||||
|
||||
if (par2 > 0.0D && par1AxisAlignedBB.maxX <= this.minX) {
|
||||
var4 = this.minX - par1AxisAlignedBB.maxX;
|
||||
|
||||
if (var4 < par2) {
|
||||
par2 = var4;
|
||||
}
|
||||
}
|
||||
|
||||
if (par2 < 0.0D && par1AxisAlignedBB.minX >= this.maxX) {
|
||||
var4 = this.maxX - par1AxisAlignedBB.minX;
|
||||
|
||||
if (var4 > par2) {
|
||||
par2 = var4;
|
||||
}
|
||||
}
|
||||
|
||||
return par2;
|
||||
} else {
|
||||
return par2;
|
||||
}
|
||||
} else {
|
||||
return par2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if instance and the argument bounding boxes overlap in the X and Z
|
||||
* dimensions, calculate the offset between them in the Y dimension. return var2
|
||||
* if the bounding boxes do not overlap or if var2 is closer to 0 then the
|
||||
* calculated offset. Otherwise return the calculated offset.
|
||||
*/
|
||||
public double calculateYOffset(AxisAlignedBB par1AxisAlignedBB, double par2) {
|
||||
if (par1AxisAlignedBB.maxX > this.minX && par1AxisAlignedBB.minX < this.maxX) {
|
||||
if (par1AxisAlignedBB.maxZ > this.minZ && par1AxisAlignedBB.minZ < this.maxZ) {
|
||||
double var4;
|
||||
|
||||
if (par2 > 0.0D && par1AxisAlignedBB.maxY <= this.minY) {
|
||||
var4 = this.minY - par1AxisAlignedBB.maxY;
|
||||
|
||||
if (var4 < par2) {
|
||||
par2 = var4;
|
||||
}
|
||||
}
|
||||
|
||||
if (par2 < 0.0D && par1AxisAlignedBB.minY >= this.maxY) {
|
||||
var4 = this.maxY - par1AxisAlignedBB.minY;
|
||||
|
||||
if (var4 > par2) {
|
||||
par2 = var4;
|
||||
}
|
||||
}
|
||||
|
||||
return par2;
|
||||
} else {
|
||||
return par2;
|
||||
}
|
||||
} else {
|
||||
return par2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if instance and the argument bounding boxes overlap in the Y and X
|
||||
* dimensions, calculate the offset between them in the Z dimension. return var2
|
||||
* if the bounding boxes do not overlap or if var2 is closer to 0 then the
|
||||
* calculated offset. Otherwise return the calculated offset.
|
||||
*/
|
||||
public double calculateZOffset(AxisAlignedBB par1AxisAlignedBB, double par2) {
|
||||
if (par1AxisAlignedBB.maxX > this.minX && par1AxisAlignedBB.minX < this.maxX) {
|
||||
if (par1AxisAlignedBB.maxY > this.minY && par1AxisAlignedBB.minY < this.maxY) {
|
||||
double var4;
|
||||
|
||||
if (par2 > 0.0D && par1AxisAlignedBB.maxZ <= this.minZ) {
|
||||
var4 = this.minZ - par1AxisAlignedBB.maxZ;
|
||||
|
||||
if (var4 < par2) {
|
||||
par2 = var4;
|
||||
}
|
||||
}
|
||||
|
||||
if (par2 < 0.0D && par1AxisAlignedBB.minZ >= this.maxZ) {
|
||||
var4 = this.maxZ - par1AxisAlignedBB.minZ;
|
||||
|
||||
if (var4 > par2) {
|
||||
par2 = var4;
|
||||
}
|
||||
}
|
||||
|
||||
return par2;
|
||||
} else {
|
||||
return par2;
|
||||
}
|
||||
} else {
|
||||
return par2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given bounding box intersects with this one. Args:
|
||||
* axisAlignedBB
|
||||
*/
|
||||
public boolean intersectsWith(AxisAlignedBB par1AxisAlignedBB) {
|
||||
return par1AxisAlignedBB.maxX > this.minX && par1AxisAlignedBB.minX < this.maxX
|
||||
? (par1AxisAlignedBB.maxY > this.minY && par1AxisAlignedBB.minY < this.maxY
|
||||
? par1AxisAlignedBB.maxZ > this.minZ && par1AxisAlignedBB.minZ < this.maxZ
|
||||
: false)
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Offsets the current bounding box by the specified coordinates. Args: x, y, z
|
||||
*/
|
||||
public AxisAlignedBB offset(double par1, double par3, double par5) {
|
||||
this.minX += par1;
|
||||
this.minY += par3;
|
||||
this.minZ += par5;
|
||||
this.maxX += par1;
|
||||
this.maxY += par3;
|
||||
this.maxZ += par5;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the supplied Vec3D is completely inside the bounding box
|
||||
*/
|
||||
public boolean isVecInside(Vec3 par1Vec3) {
|
||||
return par1Vec3.xCoord > this.minX && par1Vec3.xCoord < this.maxX
|
||||
? (par1Vec3.yCoord > this.minY && par1Vec3.yCoord < this.maxY
|
||||
? par1Vec3.zCoord > this.minZ && par1Vec3.zCoord < this.maxZ
|
||||
: false)
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the average length of the edges of the bounding box.
|
||||
*/
|
||||
public double getAverageEdgeLength() {
|
||||
double var1 = this.maxX - this.minX;
|
||||
double var3 = this.maxY - this.minY;
|
||||
double var5 = this.maxZ - this.minZ;
|
||||
return (var1 + var3 + var5) / 3.0D;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bounding box that is inset by the specified amounts
|
||||
*/
|
||||
public AxisAlignedBB contract(double par1, double par3, double par5) {
|
||||
double var7 = this.minX + par1;
|
||||
double var9 = this.minY + par3;
|
||||
double var11 = this.minZ + par5;
|
||||
double var13 = this.maxX - par1;
|
||||
double var15 = this.maxY - par3;
|
||||
double var17 = this.maxZ - par5;
|
||||
return getAABBPool().getAABB(var7, var9, var11, var13, var15, var17);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the bounding box.
|
||||
*/
|
||||
public AxisAlignedBB copy() {
|
||||
return getAABBPool().getAABB(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ);
|
||||
}
|
||||
|
||||
public MovingObjectPosition calculateIntercept(Vec3 par1Vec3, Vec3 par2Vec3) {
|
||||
Vec3 var3 = par1Vec3.getIntermediateWithXValue(par2Vec3, this.minX);
|
||||
Vec3 var4 = par1Vec3.getIntermediateWithXValue(par2Vec3, this.maxX);
|
||||
Vec3 var5 = par1Vec3.getIntermediateWithYValue(par2Vec3, this.minY);
|
||||
Vec3 var6 = par1Vec3.getIntermediateWithYValue(par2Vec3, this.maxY);
|
||||
Vec3 var7 = par1Vec3.getIntermediateWithZValue(par2Vec3, this.minZ);
|
||||
Vec3 var8 = par1Vec3.getIntermediateWithZValue(par2Vec3, this.maxZ);
|
||||
|
||||
if (!this.isVecInYZ(var3)) {
|
||||
var3 = null;
|
||||
}
|
||||
|
||||
if (!this.isVecInYZ(var4)) {
|
||||
var4 = null;
|
||||
}
|
||||
|
||||
if (!this.isVecInXZ(var5)) {
|
||||
var5 = null;
|
||||
}
|
||||
|
||||
if (!this.isVecInXZ(var6)) {
|
||||
var6 = null;
|
||||
}
|
||||
|
||||
if (!this.isVecInXY(var7)) {
|
||||
var7 = null;
|
||||
}
|
||||
|
||||
if (!this.isVecInXY(var8)) {
|
||||
var8 = null;
|
||||
}
|
||||
|
||||
Vec3 var9 = null;
|
||||
|
||||
if (var3 != null && (var9 == null || par1Vec3.squareDistanceTo(var3) < par1Vec3.squareDistanceTo(var9))) {
|
||||
var9 = var3;
|
||||
}
|
||||
|
||||
if (var4 != null && (var9 == null || par1Vec3.squareDistanceTo(var4) < par1Vec3.squareDistanceTo(var9))) {
|
||||
var9 = var4;
|
||||
}
|
||||
|
||||
if (var5 != null && (var9 == null || par1Vec3.squareDistanceTo(var5) < par1Vec3.squareDistanceTo(var9))) {
|
||||
var9 = var5;
|
||||
}
|
||||
|
||||
if (var6 != null && (var9 == null || par1Vec3.squareDistanceTo(var6) < par1Vec3.squareDistanceTo(var9))) {
|
||||
var9 = var6;
|
||||
}
|
||||
|
||||
if (var7 != null && (var9 == null || par1Vec3.squareDistanceTo(var7) < par1Vec3.squareDistanceTo(var9))) {
|
||||
var9 = var7;
|
||||
}
|
||||
|
||||
if (var8 != null && (var9 == null || par1Vec3.squareDistanceTo(var8) < par1Vec3.squareDistanceTo(var9))) {
|
||||
var9 = var8;
|
||||
}
|
||||
|
||||
if (var9 == null) {
|
||||
return null;
|
||||
} else {
|
||||
byte var10 = -1;
|
||||
|
||||
if (var9 == var3) {
|
||||
var10 = 4;
|
||||
}
|
||||
|
||||
if (var9 == var4) {
|
||||
var10 = 5;
|
||||
}
|
||||
|
||||
if (var9 == var5) {
|
||||
var10 = 0;
|
||||
}
|
||||
|
||||
if (var9 == var6) {
|
||||
var10 = 1;
|
||||
}
|
||||
|
||||
if (var9 == var7) {
|
||||
var10 = 2;
|
||||
}
|
||||
|
||||
if (var9 == var8) {
|
||||
var10 = 3;
|
||||
}
|
||||
|
||||
return new MovingObjectPosition(0, 0, 0, var10, var9);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified vector is within the YZ dimensions of the bounding
|
||||
* box. Args: Vec3D
|
||||
*/
|
||||
private boolean isVecInYZ(Vec3 par1Vec3) {
|
||||
return par1Vec3 == null ? false
|
||||
: par1Vec3.yCoord >= this.minY && par1Vec3.yCoord <= this.maxY && par1Vec3.zCoord >= this.minZ
|
||||
&& par1Vec3.zCoord <= this.maxZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified vector is within the XZ dimensions of the bounding
|
||||
* box. Args: Vec3D
|
||||
*/
|
||||
private boolean isVecInXZ(Vec3 par1Vec3) {
|
||||
return par1Vec3 == null ? false
|
||||
: par1Vec3.xCoord >= this.minX && par1Vec3.xCoord <= this.maxX && par1Vec3.zCoord >= this.minZ
|
||||
&& par1Vec3.zCoord <= this.maxZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified vector is within the XY dimensions of the bounding
|
||||
* box. Args: Vec3D
|
||||
*/
|
||||
private boolean isVecInXY(Vec3 par1Vec3) {
|
||||
return par1Vec3 == null ? false
|
||||
: par1Vec3.xCoord >= this.minX && par1Vec3.xCoord <= this.maxX && par1Vec3.yCoord >= this.minY
|
||||
&& par1Vec3.yCoord <= this.maxY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bounding box to the same bounds as the bounding box passed in. Args:
|
||||
* axisAlignedBB
|
||||
*/
|
||||
public void setBB(AxisAlignedBB par1AxisAlignedBB) {
|
||||
this.minX = par1AxisAlignedBB.minX;
|
||||
this.minY = par1AxisAlignedBB.minY;
|
||||
this.minZ = par1AxisAlignedBB.minZ;
|
||||
this.maxX = par1AxisAlignedBB.maxX;
|
||||
this.maxY = par1AxisAlignedBB.maxY;
|
||||
this.maxZ = par1AxisAlignedBB.maxZ;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "box[" + this.minX + ", " + this.minY + ", " + this.minZ + " -> " + this.maxX + ", " + this.maxY + ", "
|
||||
+ this.maxZ + "]";
|
||||
}
|
||||
}
|
140
sp-server/src/main/java/net/minecraft/src/BanEntry.java
Normal file
140
sp-server/src/main/java/net/minecraft/src/BanEntry.java
Normal file
|
@ -0,0 +1,140 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.regex.Pattern;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class BanEntry {
|
||||
public static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
|
||||
private final String username;
|
||||
private Date banStartDate = new Date();
|
||||
private String bannedBy = "(Unknown)";
|
||||
private Date banEndDate = null;
|
||||
private String reason = "Banned by an operator.";
|
||||
|
||||
public BanEntry(String par1Str) {
|
||||
this.username = par1Str;
|
||||
}
|
||||
|
||||
public String getBannedUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public Date getBanStartDate() {
|
||||
return this.banStartDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* null == start ban now
|
||||
*/
|
||||
public void setBanStartDate(Date par1Date) {
|
||||
this.banStartDate = par1Date != null ? par1Date : new Date();
|
||||
}
|
||||
|
||||
public String getBannedBy() {
|
||||
return this.bannedBy;
|
||||
}
|
||||
|
||||
public void setBannedBy(String par1Str) {
|
||||
this.bannedBy = par1Str;
|
||||
}
|
||||
|
||||
public Date getBanEndDate() {
|
||||
return this.banEndDate;
|
||||
}
|
||||
|
||||
public void setBanEndDate(Date par1Date) {
|
||||
this.banEndDate = par1Date;
|
||||
}
|
||||
|
||||
public boolean hasBanExpired() {
|
||||
return this.banEndDate == null ? false : this.banEndDate.before(new Date());
|
||||
}
|
||||
|
||||
public String getBanReason() {
|
||||
return this.reason;
|
||||
}
|
||||
|
||||
public void setBanReason(String par1Str) {
|
||||
this.reason = par1Str;
|
||||
}
|
||||
|
||||
public String buildBanString() {
|
||||
StringBuilder var1 = new StringBuilder();
|
||||
var1.append(this.getBannedUsername());
|
||||
var1.append("|");
|
||||
var1.append(dateFormat.format(this.getBanStartDate()));
|
||||
var1.append("|");
|
||||
var1.append(this.getBannedBy());
|
||||
var1.append("|");
|
||||
var1.append(this.getBanEndDate() == null ? "Forever" : dateFormat.format(this.getBanEndDate()));
|
||||
var1.append("|");
|
||||
var1.append(this.getBanReason());
|
||||
return var1.toString();
|
||||
}
|
||||
|
||||
public static BanEntry parse(String par0Str) {
|
||||
if (par0Str.trim().length() < 2) {
|
||||
return null;
|
||||
} else {
|
||||
String[] var1 = par0Str.trim().split(Pattern.quote("|"), 5);
|
||||
BanEntry var2 = new BanEntry(var1[0].trim());
|
||||
byte var3 = 0;
|
||||
int var10000 = var1.length;
|
||||
int var7 = var3 + 1;
|
||||
|
||||
if (var10000 <= var7) {
|
||||
return var2;
|
||||
} else {
|
||||
try {
|
||||
var2.setBanStartDate(dateFormat.parse(var1[var7].trim()));
|
||||
} catch (ParseException var6) {
|
||||
MinecraftServer.getServer().getLogAgent()
|
||||
.logWarningException("Could not read creation date format for ban entry \'"
|
||||
+ var2.getBannedUsername() + "\' (was: \'" + var1[var7] + "\')", var6);
|
||||
}
|
||||
|
||||
var10000 = var1.length;
|
||||
++var7;
|
||||
|
||||
if (var10000 <= var7) {
|
||||
return var2;
|
||||
} else {
|
||||
var2.setBannedBy(var1[var7].trim());
|
||||
var10000 = var1.length;
|
||||
++var7;
|
||||
|
||||
if (var10000 <= var7) {
|
||||
return var2;
|
||||
} else {
|
||||
try {
|
||||
String var4 = var1[var7].trim();
|
||||
|
||||
if (!var4.equalsIgnoreCase("Forever") && var4.length() > 0) {
|
||||
var2.setBanEndDate(dateFormat.parse(var4));
|
||||
}
|
||||
} catch (ParseException var5) {
|
||||
MinecraftServer.getServer().getLogAgent()
|
||||
.logWarningException(
|
||||
"Could not read expiry date format for ban entry \'"
|
||||
+ var2.getBannedUsername() + "\' (was: \'" + var1[var7] + "\')",
|
||||
var5);
|
||||
}
|
||||
|
||||
var10000 = var1.length;
|
||||
++var7;
|
||||
|
||||
if (var10000 <= var7) {
|
||||
return var2;
|
||||
} else {
|
||||
var2.setBanReason(var1[var7].trim());
|
||||
return var2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
137
sp-server/src/main/java/net/minecraft/src/BanList.java
Normal file
137
sp-server/src/main/java/net/minecraft/src/BanList.java
Normal file
|
@ -0,0 +1,137 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class BanList {
|
||||
private final LowerStringMap theBanList = new LowerStringMap();
|
||||
private final File fileName;
|
||||
|
||||
/** set to true if not singlePlayer */
|
||||
private boolean listActive = true;
|
||||
|
||||
public BanList(File par1File) {
|
||||
this.fileName = par1File;
|
||||
}
|
||||
|
||||
public boolean isListActive() {
|
||||
return this.listActive;
|
||||
}
|
||||
|
||||
public void setListActive(boolean par1) {
|
||||
this.listActive = par1;
|
||||
}
|
||||
|
||||
/**
|
||||
* removes expired Bans before returning
|
||||
*/
|
||||
public Map getBannedList() {
|
||||
this.removeExpiredBans();
|
||||
return this.theBanList;
|
||||
}
|
||||
|
||||
public boolean isBanned(String par1Str) {
|
||||
if (!this.isListActive()) {
|
||||
return false;
|
||||
} else {
|
||||
this.removeExpiredBans();
|
||||
return this.theBanList.containsKey(par1Str);
|
||||
}
|
||||
}
|
||||
|
||||
public void put(BanEntry par1BanEntry) {
|
||||
this.theBanList.putLower(par1BanEntry.getBannedUsername(), par1BanEntry);
|
||||
this.saveToFileWithHeader();
|
||||
}
|
||||
|
||||
public void remove(String par1Str) {
|
||||
this.theBanList.remove(par1Str);
|
||||
this.saveToFileWithHeader();
|
||||
}
|
||||
|
||||
public void removeExpiredBans() {
|
||||
Iterator var1 = this.theBanList.values().iterator();
|
||||
|
||||
while (var1.hasNext()) {
|
||||
BanEntry var2 = (BanEntry) var1.next();
|
||||
|
||||
if (var2.hasBanExpired()) {
|
||||
var1.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the ban list from the file (adds every entry, does not clear the
|
||||
* current list).
|
||||
*/
|
||||
public void loadBanList() {
|
||||
if (this.fileName.isFile()) {
|
||||
BufferedReader var1;
|
||||
|
||||
try {
|
||||
var1 = new BufferedReader(new FileReader(this.fileName));
|
||||
} catch (FileNotFoundException var4) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
String var2;
|
||||
|
||||
try {
|
||||
while ((var2 = var1.readLine()) != null) {
|
||||
if (!var2.startsWith("#")) {
|
||||
BanEntry var3 = BanEntry.parse(var2);
|
||||
|
||||
if (var3 != null) {
|
||||
this.theBanList.putLower(var3.getBannedUsername(), var3);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException var5) {
|
||||
MinecraftServer.getServer().getLogAgent().logSevereException("Could not load ban list", var5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void saveToFileWithHeader() {
|
||||
this.saveToFile(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* par1: include header
|
||||
*/
|
||||
public void saveToFile(boolean par1) {
|
||||
this.removeExpiredBans();
|
||||
|
||||
try {
|
||||
PrintWriter var2 = new PrintWriter(new FileWriter(this.fileName, false));
|
||||
|
||||
if (par1) {
|
||||
var2.println("# Updated " + (new SimpleDateFormat()).format(new Date()) + " by Minecraft " + "1.5.2");
|
||||
var2.println("# victim name | ban date | banned by | banned until | reason");
|
||||
var2.println();
|
||||
}
|
||||
|
||||
Iterator var3 = this.theBanList.values().iterator();
|
||||
|
||||
while (var3.hasNext()) {
|
||||
BanEntry var4 = (BanEntry) var3.next();
|
||||
var2.println(var4.buildBanString());
|
||||
}
|
||||
|
||||
var2.close();
|
||||
} catch (IOException var5) {
|
||||
MinecraftServer.getServer().getLogAgent().logSevereException("Could not save ban list", var5);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
public class BehaviorDefaultDispenseItem implements IBehaviorDispenseItem {
|
||||
/**
|
||||
* Dispenses the specified ItemStack from a dispenser.
|
||||
*/
|
||||
public final ItemStack dispense(IBlockSource par1IBlockSource, ItemStack par2ItemStack) {
|
||||
ItemStack var3 = this.dispenseStack(par1IBlockSource, par2ItemStack);
|
||||
this.playDispenseSound(par1IBlockSource);
|
||||
this.spawnDispenseParticles(par1IBlockSource, BlockDispenser.getFacing(par1IBlockSource.getBlockMetadata()));
|
||||
return var3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispense the specified stack, play the dispense sound and spawn particles.
|
||||
*/
|
||||
protected ItemStack dispenseStack(IBlockSource par1IBlockSource, ItemStack par2ItemStack) {
|
||||
EnumFacing var3 = BlockDispenser.getFacing(par1IBlockSource.getBlockMetadata());
|
||||
IPosition var4 = BlockDispenser.getIPositionFromBlockSource(par1IBlockSource);
|
||||
ItemStack var5 = par2ItemStack.splitStack(1);
|
||||
doDispense(par1IBlockSource.getWorld(), var5, 6, var3, var4);
|
||||
return par2ItemStack;
|
||||
}
|
||||
|
||||
public static void doDispense(World par0World, ItemStack par1ItemStack, int par2, EnumFacing par3EnumFacing,
|
||||
IPosition par4IPosition) {
|
||||
double var5 = par4IPosition.getX();
|
||||
double var7 = par4IPosition.getY();
|
||||
double var9 = par4IPosition.getZ();
|
||||
EntityItem var11 = new EntityItem(par0World, var5, var7 - 0.3D, var9, par1ItemStack);
|
||||
double var12 = par0World.rand.nextDouble() * 0.1D + 0.2D;
|
||||
var11.motionX = (double) par3EnumFacing.getFrontOffsetX() * var12;
|
||||
var11.motionY = 0.20000000298023224D;
|
||||
var11.motionZ = (double) par3EnumFacing.getFrontOffsetZ() * var12;
|
||||
var11.motionX += par0World.rand.nextGaussian() * 0.007499999832361937D * (double) par2;
|
||||
var11.motionY += par0World.rand.nextGaussian() * 0.007499999832361937D * (double) par2;
|
||||
var11.motionZ += par0World.rand.nextGaussian() * 0.007499999832361937D * (double) par2;
|
||||
par0World.spawnEntityInWorld(var11);
|
||||
}
|
||||
|
||||
/**
|
||||
* Play the dispense sound from the specified block.
|
||||
*/
|
||||
protected void playDispenseSound(IBlockSource par1IBlockSource) {
|
||||
par1IBlockSource.getWorld().playAuxSFX(1000, par1IBlockSource.getXInt(), par1IBlockSource.getYInt(),
|
||||
par1IBlockSource.getZInt(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order clients to display dispense particles from the specified block and
|
||||
* facing.
|
||||
*/
|
||||
protected void spawnDispenseParticles(IBlockSource par1IBlockSource, EnumFacing par2EnumFacing) {
|
||||
par1IBlockSource.getWorld().playAuxSFX(2000, par1IBlockSource.getXInt(), par1IBlockSource.getYInt(),
|
||||
par1IBlockSource.getZInt(), this.func_82488_a(par2EnumFacing));
|
||||
}
|
||||
|
||||
private int func_82488_a(EnumFacing par1EnumFacing) {
|
||||
return par1EnumFacing.getFrontOffsetX() + 1 + (par1EnumFacing.getFrontOffsetZ() + 1) * 3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
final class BehaviorDispenseArmor extends BehaviorDefaultDispenseItem {
|
||||
/**
|
||||
* Dispense the specified stack, play the dispense sound and spawn particles.
|
||||
*/
|
||||
protected ItemStack dispenseStack(IBlockSource par1IBlockSource, ItemStack par2ItemStack) {
|
||||
EnumFacing var3 = BlockDispenser.getFacing(par1IBlockSource.getBlockMetadata());
|
||||
int var4 = par1IBlockSource.getXInt() + var3.getFrontOffsetX();
|
||||
int var5 = par1IBlockSource.getYInt() + var3.getFrontOffsetY();
|
||||
int var6 = par1IBlockSource.getZInt() + var3.getFrontOffsetZ();
|
||||
AxisAlignedBB var7 = AxisAlignedBB.getAABBPool().getAABB((double) var4, (double) var5, (double) var6,
|
||||
(double) (var4 + 1), (double) (var5 + 1), (double) (var6 + 1));
|
||||
List var8 = par1IBlockSource.getWorld().selectEntitiesWithinAABB(EntityLiving.class, var7,
|
||||
new EntitySelectorArmoredMob(par2ItemStack));
|
||||
|
||||
if (var8.size() > 0) {
|
||||
EntityLiving var9 = (EntityLiving) var8.get(0);
|
||||
int var10 = var9 instanceof EntityPlayer ? 1 : 0;
|
||||
int var11 = EntityLiving.getArmorPosition(par2ItemStack);
|
||||
ItemStack var12 = par2ItemStack.copy();
|
||||
var12.stackSize = 1;
|
||||
var9.setCurrentItemOrArmor(var11 - var10, var12);
|
||||
var9.func_96120_a(var11, 2.0F);
|
||||
--par2ItemStack.stackSize;
|
||||
return par2ItemStack;
|
||||
} else {
|
||||
return super.dispenseStack(par1IBlockSource, par2ItemStack);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
final class BehaviorDispenseItemProvider implements IBehaviorDispenseItem {
|
||||
/**
|
||||
* Dispenses the specified ItemStack from a dispenser.
|
||||
*/
|
||||
public ItemStack dispense(IBlockSource par1IBlockSource, ItemStack par2ItemStack) {
|
||||
return par2ItemStack;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
final class BehaviorDispenseMinecart extends BehaviorDefaultDispenseItem {
|
||||
private final BehaviorDefaultDispenseItem field_96465_b = new BehaviorDefaultDispenseItem();
|
||||
|
||||
/**
|
||||
* Dispense the specified stack, play the dispense sound and spawn particles.
|
||||
*/
|
||||
public ItemStack dispenseStack(IBlockSource par1IBlockSource, ItemStack par2ItemStack) {
|
||||
EnumFacing var3 = BlockDispenser.getFacing(par1IBlockSource.getBlockMetadata());
|
||||
World var4 = par1IBlockSource.getWorld();
|
||||
double var5 = par1IBlockSource.getX() + (double) ((float) var3.getFrontOffsetX() * 1.125F);
|
||||
double var7 = par1IBlockSource.getY() + (double) ((float) var3.getFrontOffsetY() * 1.125F);
|
||||
double var9 = par1IBlockSource.getZ() + (double) ((float) var3.getFrontOffsetZ() * 1.125F);
|
||||
int var11 = par1IBlockSource.getXInt() + var3.getFrontOffsetX();
|
||||
int var12 = par1IBlockSource.getYInt() + var3.getFrontOffsetY();
|
||||
int var13 = par1IBlockSource.getZInt() + var3.getFrontOffsetZ();
|
||||
int var14 = var4.getBlockId(var11, var12, var13);
|
||||
double var15;
|
||||
|
||||
if (BlockRailBase.isRailBlock(var14)) {
|
||||
var15 = 0.0D;
|
||||
} else {
|
||||
if (var14 != 0 || !BlockRailBase.isRailBlock(var4.getBlockId(var11, var12 - 1, var13))) {
|
||||
return this.field_96465_b.dispense(par1IBlockSource, par2ItemStack);
|
||||
}
|
||||
|
||||
var15 = -1.0D;
|
||||
}
|
||||
|
||||
EntityMinecart var17 = EntityMinecart.createMinecart(var4, var5, var7 + var15, var9,
|
||||
((ItemMinecart) par2ItemStack.getItem()).minecartType);
|
||||
var4.spawnEntityInWorld(var17);
|
||||
par2ItemStack.splitStack(1);
|
||||
return par2ItemStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Play the dispense sound from the specified block.
|
||||
*/
|
||||
protected void playDispenseSound(IBlockSource par1IBlockSource) {
|
||||
par1IBlockSource.getWorld().playAuxSFX(1000, par1IBlockSource.getXInt(), par1IBlockSource.getYInt(),
|
||||
par1IBlockSource.getZInt(), 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
public abstract class BehaviorProjectileDispense extends BehaviorDefaultDispenseItem {
|
||||
/**
|
||||
* Dispense the specified stack, play the dispense sound and spawn particles.
|
||||
*/
|
||||
public ItemStack dispenseStack(IBlockSource par1IBlockSource, ItemStack par2ItemStack) {
|
||||
World var3 = par1IBlockSource.getWorld();
|
||||
IPosition var4 = BlockDispenser.getIPositionFromBlockSource(par1IBlockSource);
|
||||
EnumFacing var5 = BlockDispenser.getFacing(par1IBlockSource.getBlockMetadata());
|
||||
IProjectile var6 = this.getProjectileEntity(var3, var4);
|
||||
var6.setThrowableHeading((double) var5.getFrontOffsetX(), (double) ((float) var5.getFrontOffsetY() + 0.1F),
|
||||
(double) var5.getFrontOffsetZ(), this.func_82500_b(), this.func_82498_a());
|
||||
var3.spawnEntityInWorld((Entity) var6);
|
||||
par2ItemStack.splitStack(1);
|
||||
return par2ItemStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Play the dispense sound from the specified block.
|
||||
*/
|
||||
protected void playDispenseSound(IBlockSource par1IBlockSource) {
|
||||
par1IBlockSource.getWorld().playAuxSFX(1002, par1IBlockSource.getXInt(), par1IBlockSource.getYInt(),
|
||||
par1IBlockSource.getZInt(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the projectile entity spawned by this dispense behavior.
|
||||
*/
|
||||
protected abstract IProjectile getProjectileEntity(World var1, IPosition var2);
|
||||
|
||||
protected float func_82498_a() {
|
||||
return 6.0F;
|
||||
}
|
||||
|
||||
protected float func_82500_b() {
|
||||
return 1.1F;
|
||||
}
|
||||
}
|
90
sp-server/src/main/java/net/minecraft/src/BiomeCache.java
Normal file
90
sp-server/src/main/java/net/minecraft/src/BiomeCache.java
Normal file
|
@ -0,0 +1,90 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BiomeCache {
|
||||
/** Reference to the WorldChunkManager */
|
||||
private final WorldChunkManager chunkManager;
|
||||
|
||||
/** The last time this BiomeCache was cleaned, in milliseconds. */
|
||||
private long lastCleanupTime = 0L;
|
||||
|
||||
/**
|
||||
* The map of keys to BiomeCacheBlocks. Keys are based on the chunk x, z
|
||||
* coordinates as (x | z << 32).
|
||||
*/
|
||||
private LongHashMap cacheMap = new LongHashMap();
|
||||
|
||||
/** The list of cached BiomeCacheBlocks */
|
||||
private List cache = new ArrayList();
|
||||
|
||||
public BiomeCache(WorldChunkManager par1WorldChunkManager) {
|
||||
this.chunkManager = par1WorldChunkManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a biome cache block at location specified.
|
||||
*/
|
||||
public BiomeCacheBlock getBiomeCacheBlock(int par1, int par2) {
|
||||
par1 >>= 4;
|
||||
par2 >>= 4;
|
||||
long var3 = (long) par1 & 4294967295L | ((long) par2 & 4294967295L) << 32;
|
||||
BiomeCacheBlock var5 = (BiomeCacheBlock) this.cacheMap.getValueByKey(var3);
|
||||
|
||||
if (var5 == null) {
|
||||
var5 = new BiomeCacheBlock(this, par1, par2);
|
||||
this.cacheMap.add(var3, var5);
|
||||
this.cache.add(var5);
|
||||
}
|
||||
|
||||
var5.lastAccessTime = System.currentTimeMillis();
|
||||
return var5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the BiomeGenBase related to the x, z position from the cache.
|
||||
*/
|
||||
public BiomeGenBase getBiomeGenAt(int par1, int par2) {
|
||||
return this.getBiomeCacheBlock(par1, par2).getBiomeGenAt(par1, par2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes BiomeCacheBlocks from this cache that haven't been accessed in at
|
||||
* least 30 seconds.
|
||||
*/
|
||||
public void cleanupCache() {
|
||||
long var1 = System.currentTimeMillis();
|
||||
long var3 = var1 - this.lastCleanupTime;
|
||||
|
||||
if (var3 > 7500L || var3 < 0L) {
|
||||
this.lastCleanupTime = var1;
|
||||
|
||||
for (int var5 = 0; var5 < this.cache.size(); ++var5) {
|
||||
BiomeCacheBlock var6 = (BiomeCacheBlock) this.cache.get(var5);
|
||||
long var7 = var1 - var6.lastAccessTime;
|
||||
|
||||
if (var7 > 30000L || var7 < 0L) {
|
||||
this.cache.remove(var5--);
|
||||
long var9 = (long) var6.xPosition & 4294967295L | ((long) var6.zPosition & 4294967295L) << 32;
|
||||
this.cacheMap.remove(var9);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the array of cached biome types in the BiomeCacheBlock at the given
|
||||
* location.
|
||||
*/
|
||||
public BiomeGenBase[] getCachedBiomes(int par1, int par2) {
|
||||
return this.getBiomeCacheBlock(par1, par2).biomes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the world chunk manager object for a biome list.
|
||||
*/
|
||||
static WorldChunkManager getChunkManager(BiomeCache par0BiomeCache) {
|
||||
return par0BiomeCache.chunkManager;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
public class BiomeCacheBlock {
|
||||
/** An array of chunk temperatures saved by this cache. */
|
||||
public float[] temperatureValues;
|
||||
|
||||
/** An array of chunk rainfall values saved by this cache. */
|
||||
public float[] rainfallValues;
|
||||
|
||||
/** The array of biome types stored in this BiomeCacheBlock. */
|
||||
public BiomeGenBase[] biomes;
|
||||
|
||||
/** The x coordinate of the BiomeCacheBlock. */
|
||||
public int xPosition;
|
||||
|
||||
/** The z coordinate of the BiomeCacheBlock. */
|
||||
public int zPosition;
|
||||
|
||||
/** The last time this BiomeCacheBlock was accessed, in milliseconds. */
|
||||
public long lastAccessTime;
|
||||
|
||||
/** The BiomeCache object that contains this BiomeCacheBlock */
|
||||
final BiomeCache theBiomeCache;
|
||||
|
||||
public BiomeCacheBlock(BiomeCache par1BiomeCache, int par2, int par3) {
|
||||
this.theBiomeCache = par1BiomeCache;
|
||||
this.temperatureValues = new float[256];
|
||||
this.rainfallValues = new float[256];
|
||||
this.biomes = new BiomeGenBase[256];
|
||||
this.xPosition = par2;
|
||||
this.zPosition = par3;
|
||||
BiomeCache.getChunkManager(par1BiomeCache).getTemperatures(this.temperatureValues, par2 << 4, par3 << 4, 16,
|
||||
16);
|
||||
BiomeCache.getChunkManager(par1BiomeCache).getRainfall(this.rainfallValues, par2 << 4, par3 << 4, 16, 16);
|
||||
BiomeCache.getChunkManager(par1BiomeCache).getBiomeGenAt(this.biomes, par2 << 4, par3 << 4, 16, 16, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the BiomeGenBase related to the x, z position from the cache block.
|
||||
*/
|
||||
public BiomeGenBase getBiomeGenAt(int par1, int par2) {
|
||||
return this.biomes[par1 & 15 | (par2 & 15) << 4];
|
||||
}
|
||||
}
|
405
sp-server/src/main/java/net/minecraft/src/BiomeDecorator.java
Normal file
405
sp-server/src/main/java/net/minecraft/src/BiomeDecorator.java
Normal file
|
@ -0,0 +1,405 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class BiomeDecorator {
|
||||
/** The world the BiomeDecorator is currently decorating */
|
||||
protected World currentWorld;
|
||||
|
||||
/** The Biome Decorator's random number generator. */
|
||||
protected Random randomGenerator;
|
||||
|
||||
/** The X-coordinate of the chunk currently being decorated */
|
||||
protected int chunk_X;
|
||||
|
||||
/** The Z-coordinate of the chunk currently being decorated */
|
||||
protected int chunk_Z;
|
||||
|
||||
/** The biome generator object. */
|
||||
protected BiomeGenBase biome;
|
||||
|
||||
/** The clay generator. */
|
||||
protected WorldGenerator clayGen = new WorldGenClay(4);
|
||||
|
||||
/** The sand generator. */
|
||||
protected WorldGenerator sandGen;
|
||||
|
||||
/** The gravel generator. */
|
||||
protected WorldGenerator gravelAsSandGen;
|
||||
|
||||
/** The dirt generator. */
|
||||
protected WorldGenerator dirtGen;
|
||||
protected WorldGenerator gravelGen;
|
||||
protected WorldGenerator coalGen;
|
||||
protected WorldGenerator ironGen;
|
||||
|
||||
/** Field that holds gold WorldGenMinable */
|
||||
protected WorldGenerator goldGen;
|
||||
|
||||
/** Field that holds redstone WorldGenMinable */
|
||||
protected WorldGenerator redstoneGen;
|
||||
|
||||
/** Field that holds diamond WorldGenMinable */
|
||||
protected WorldGenerator diamondGen;
|
||||
|
||||
/** Field that holds Lapis WorldGenMinable */
|
||||
protected WorldGenerator lapisGen;
|
||||
|
||||
/** Field that holds one of the plantYellow WorldGenFlowers */
|
||||
protected WorldGenerator plantYellowGen;
|
||||
|
||||
/** Field that holds one of the plantRed WorldGenFlowers */
|
||||
protected WorldGenerator plantRedGen;
|
||||
|
||||
/** Field that holds mushroomBrown WorldGenFlowers */
|
||||
protected WorldGenerator mushroomBrownGen;
|
||||
|
||||
/** Field that holds mushroomRed WorldGenFlowers */
|
||||
protected WorldGenerator mushroomRedGen;
|
||||
|
||||
/** Field that holds big mushroom generator */
|
||||
protected WorldGenerator bigMushroomGen;
|
||||
|
||||
/** Field that holds WorldGenReed */
|
||||
protected WorldGenerator reedGen;
|
||||
|
||||
/** Field that holds WorldGenCactus */
|
||||
protected WorldGenerator cactusGen;
|
||||
|
||||
/** The water lily generation! */
|
||||
protected WorldGenerator waterlilyGen;
|
||||
|
||||
/** Amount of waterlilys per chunk. */
|
||||
protected int waterlilyPerChunk;
|
||||
|
||||
/**
|
||||
* The number of trees to attempt to generate per chunk. Up to 10 in forests,
|
||||
* none in deserts.
|
||||
*/
|
||||
protected int treesPerChunk;
|
||||
|
||||
/**
|
||||
* The number of yellow flower patches to generate per chunk. The game generates
|
||||
* much less than this number, since it attempts to generate them at a random
|
||||
* altitude.
|
||||
*/
|
||||
protected int flowersPerChunk;
|
||||
|
||||
/** The amount of tall grass to generate per chunk. */
|
||||
protected int grassPerChunk;
|
||||
|
||||
/**
|
||||
* The number of dead bushes to generate per chunk. Used in deserts and swamps.
|
||||
*/
|
||||
protected int deadBushPerChunk;
|
||||
|
||||
/**
|
||||
* The number of extra mushroom patches per chunk. It generates 1/4 this number
|
||||
* in brown mushroom patches, and 1/8 this number in red mushroom patches. These
|
||||
* mushrooms go beyond the default base number of mushrooms.
|
||||
*/
|
||||
protected int mushroomsPerChunk;
|
||||
|
||||
/**
|
||||
* The number of reeds to generate per chunk. Reeds won't generate if the
|
||||
* randomly selected placement is unsuitable.
|
||||
*/
|
||||
protected int reedsPerChunk;
|
||||
|
||||
/**
|
||||
* The number of cactus plants to generate per chunk. Cacti only work on sand.
|
||||
*/
|
||||
protected int cactiPerChunk;
|
||||
|
||||
/**
|
||||
* The number of sand patches to generate per chunk. Sand patches only generate
|
||||
* when part of it is underwater.
|
||||
*/
|
||||
protected int sandPerChunk;
|
||||
|
||||
/**
|
||||
* The number of sand patches to generate per chunk. Sand patches only generate
|
||||
* when part of it is underwater. There appear to be two separate fields for
|
||||
* this.
|
||||
*/
|
||||
protected int sandPerChunk2;
|
||||
|
||||
/**
|
||||
* The number of clay patches to generate per chunk. Only generates when part of
|
||||
* it is underwater.
|
||||
*/
|
||||
protected int clayPerChunk;
|
||||
|
||||
/** Amount of big mushrooms per chunk */
|
||||
protected int bigMushroomsPerChunk;
|
||||
|
||||
/** True if decorator should generate surface lava & water */
|
||||
public boolean generateLakes;
|
||||
|
||||
public BiomeDecorator(BiomeGenBase par1BiomeGenBase) {
|
||||
this.sandGen = new WorldGenSand(7, Block.sand.blockID);
|
||||
this.gravelAsSandGen = new WorldGenSand(6, Block.gravel.blockID);
|
||||
this.dirtGen = new WorldGenMinable(Block.dirt.blockID, 32);
|
||||
this.gravelGen = new WorldGenMinable(Block.gravel.blockID, 32);
|
||||
this.coalGen = new WorldGenMinable(Block.oreCoal.blockID, 16);
|
||||
this.ironGen = new WorldGenMinable(Block.oreIron.blockID, 8);
|
||||
this.goldGen = new WorldGenMinable(Block.oreGold.blockID, 8);
|
||||
this.redstoneGen = new WorldGenMinable(Block.oreRedstone.blockID, 7);
|
||||
this.diamondGen = new WorldGenMinable(Block.oreDiamond.blockID, 7);
|
||||
this.lapisGen = new WorldGenMinable(Block.oreLapis.blockID, 6);
|
||||
this.plantYellowGen = new WorldGenFlowers(Block.plantYellow.blockID);
|
||||
this.plantRedGen = new WorldGenFlowers(Block.plantRed.blockID);
|
||||
this.mushroomBrownGen = new WorldGenFlowers(Block.mushroomBrown.blockID);
|
||||
this.mushroomRedGen = new WorldGenFlowers(Block.mushroomRed.blockID);
|
||||
this.bigMushroomGen = new WorldGenBigMushroom();
|
||||
this.reedGen = new WorldGenReed();
|
||||
this.cactusGen = new WorldGenCactus();
|
||||
this.waterlilyGen = new WorldGenWaterlily();
|
||||
this.waterlilyPerChunk = 0;
|
||||
this.treesPerChunk = 0;
|
||||
this.flowersPerChunk = 2;
|
||||
this.grassPerChunk = 1;
|
||||
this.deadBushPerChunk = 0;
|
||||
this.mushroomsPerChunk = 0;
|
||||
this.reedsPerChunk = 0;
|
||||
this.cactiPerChunk = 0;
|
||||
this.sandPerChunk = 1;
|
||||
this.sandPerChunk2 = 3;
|
||||
this.clayPerChunk = 1;
|
||||
this.bigMushroomsPerChunk = 0;
|
||||
this.generateLakes = true;
|
||||
this.biome = par1BiomeGenBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorates the world. Calls code that was formerly (pre-1.8) in
|
||||
* ChunkProviderGenerate.populate
|
||||
*/
|
||||
public void decorate(World par1World, Random par2Random, int par3, int par4) {
|
||||
if (this.currentWorld != null) {
|
||||
throw new RuntimeException("Already decorating!!");
|
||||
} else {
|
||||
this.currentWorld = par1World;
|
||||
this.randomGenerator = par2Random;
|
||||
this.chunk_X = par3;
|
||||
this.chunk_Z = par4;
|
||||
this.decorate();
|
||||
this.currentWorld = null;
|
||||
this.randomGenerator = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The method that does the work of actually decorating chunks
|
||||
*/
|
||||
protected void decorate() {
|
||||
this.generateOres();
|
||||
int var1;
|
||||
int var2;
|
||||
int var3;
|
||||
|
||||
for (var1 = 0; var1 < this.sandPerChunk2; ++var1) {
|
||||
var2 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var3 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
this.sandGen.generate(this.currentWorld, this.randomGenerator, var2,
|
||||
this.currentWorld.getTopSolidOrLiquidBlock(var2, var3), var3);
|
||||
}
|
||||
|
||||
for (var1 = 0; var1 < this.clayPerChunk; ++var1) {
|
||||
var2 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var3 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
this.clayGen.generate(this.currentWorld, this.randomGenerator, var2,
|
||||
this.currentWorld.getTopSolidOrLiquidBlock(var2, var3), var3);
|
||||
}
|
||||
|
||||
for (var1 = 0; var1 < this.sandPerChunk; ++var1) {
|
||||
var2 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var3 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
this.sandGen.generate(this.currentWorld, this.randomGenerator, var2,
|
||||
this.currentWorld.getTopSolidOrLiquidBlock(var2, var3), var3);
|
||||
}
|
||||
|
||||
var1 = this.treesPerChunk;
|
||||
|
||||
if (this.randomGenerator.nextInt(10) == 0) {
|
||||
++var1;
|
||||
}
|
||||
|
||||
int var4;
|
||||
|
||||
for (var2 = 0; var2 < var1; ++var2) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
WorldGenerator var5 = this.biome.getRandomWorldGenForTrees(this.randomGenerator);
|
||||
var5.setScale(1.0D, 1.0D, 1.0D);
|
||||
var5.generate(this.currentWorld, this.randomGenerator, var3, this.currentWorld.getHeightValue(var3, var4),
|
||||
var4);
|
||||
}
|
||||
|
||||
for (var2 = 0; var2 < this.bigMushroomsPerChunk; ++var2) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
this.bigMushroomGen.generate(this.currentWorld, this.randomGenerator, var3,
|
||||
this.currentWorld.getHeightValue(var3, var4), var4);
|
||||
}
|
||||
|
||||
int var7;
|
||||
|
||||
for (var2 = 0; var2 < this.flowersPerChunk; ++var2) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.randomGenerator.nextInt(128);
|
||||
var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
this.plantYellowGen.generate(this.currentWorld, this.randomGenerator, var3, var4, var7);
|
||||
|
||||
if (this.randomGenerator.nextInt(4) == 0) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.randomGenerator.nextInt(128);
|
||||
var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
this.plantRedGen.generate(this.currentWorld, this.randomGenerator, var3, var4, var7);
|
||||
}
|
||||
}
|
||||
|
||||
for (var2 = 0; var2 < this.grassPerChunk; ++var2) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.randomGenerator.nextInt(128);
|
||||
var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
WorldGenerator var6 = this.biome.getRandomWorldGenForGrass(this.randomGenerator);
|
||||
var6.generate(this.currentWorld, this.randomGenerator, var3, var4, var7);
|
||||
}
|
||||
|
||||
for (var2 = 0; var2 < this.deadBushPerChunk; ++var2) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.randomGenerator.nextInt(128);
|
||||
var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
(new WorldGenDeadBush(Block.deadBush.blockID)).generate(this.currentWorld, this.randomGenerator, var3, var4,
|
||||
var7);
|
||||
}
|
||||
|
||||
for (var2 = 0; var2 < this.waterlilyPerChunk; ++var2) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
|
||||
for (var7 = this.randomGenerator.nextInt(128); var7 > 0
|
||||
&& this.currentWorld.getBlockId(var3, var7 - 1, var4) == 0; --var7) {
|
||||
;
|
||||
}
|
||||
|
||||
this.waterlilyGen.generate(this.currentWorld, this.randomGenerator, var3, var7, var4);
|
||||
}
|
||||
|
||||
for (var2 = 0; var2 < this.mushroomsPerChunk; ++var2) {
|
||||
if (this.randomGenerator.nextInt(4) == 0) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
var7 = this.currentWorld.getHeightValue(var3, var4);
|
||||
this.mushroomBrownGen.generate(this.currentWorld, this.randomGenerator, var3, var7, var4);
|
||||
}
|
||||
|
||||
if (this.randomGenerator.nextInt(8) == 0) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
var7 = this.randomGenerator.nextInt(128);
|
||||
this.mushroomRedGen.generate(this.currentWorld, this.randomGenerator, var3, var7, var4);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.randomGenerator.nextInt(4) == 0) {
|
||||
var2 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var3 = this.randomGenerator.nextInt(128);
|
||||
var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
this.mushroomBrownGen.generate(this.currentWorld, this.randomGenerator, var2, var3, var4);
|
||||
}
|
||||
|
||||
if (this.randomGenerator.nextInt(8) == 0) {
|
||||
var2 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var3 = this.randomGenerator.nextInt(128);
|
||||
var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
this.mushroomRedGen.generate(this.currentWorld, this.randomGenerator, var2, var3, var4);
|
||||
}
|
||||
|
||||
for (var2 = 0; var2 < this.reedsPerChunk; ++var2) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
var7 = this.randomGenerator.nextInt(128);
|
||||
this.reedGen.generate(this.currentWorld, this.randomGenerator, var3, var7, var4);
|
||||
}
|
||||
|
||||
for (var2 = 0; var2 < 10; ++var2) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.randomGenerator.nextInt(128);
|
||||
var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
this.reedGen.generate(this.currentWorld, this.randomGenerator, var3, var4, var7);
|
||||
}
|
||||
|
||||
if (this.randomGenerator.nextInt(32) == 0) {
|
||||
var2 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var3 = this.randomGenerator.nextInt(128);
|
||||
var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
(new WorldGenPumpkin()).generate(this.currentWorld, this.randomGenerator, var2, var3, var4);
|
||||
}
|
||||
|
||||
for (var2 = 0; var2 < this.cactiPerChunk; ++var2) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.randomGenerator.nextInt(128);
|
||||
var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
this.cactusGen.generate(this.currentWorld, this.randomGenerator, var3, var4, var7);
|
||||
}
|
||||
|
||||
if (this.generateLakes) {
|
||||
for (var2 = 0; var2 < 50; ++var2) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.randomGenerator.nextInt(this.randomGenerator.nextInt(120) + 8);
|
||||
var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
(new WorldGenLiquids(Block.waterMoving.blockID)).generate(this.currentWorld, this.randomGenerator, var3,
|
||||
var4, var7);
|
||||
}
|
||||
|
||||
for (var2 = 0; var2 < 20; ++var2) {
|
||||
var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
var4 = this.randomGenerator
|
||||
.nextInt(this.randomGenerator.nextInt(this.randomGenerator.nextInt(112) + 8) + 8);
|
||||
var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
(new WorldGenLiquids(Block.lavaMoving.blockID)).generate(this.currentWorld, this.randomGenerator, var3,
|
||||
var4, var7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard ore generation helper. Generates most ores.
|
||||
*/
|
||||
protected void genStandardOre1(int par1, WorldGenerator par2WorldGenerator, int par3, int par4) {
|
||||
for (int var5 = 0; var5 < par1; ++var5) {
|
||||
int var6 = this.chunk_X + this.randomGenerator.nextInt(16);
|
||||
int var7 = this.randomGenerator.nextInt(par4 - par3) + par3;
|
||||
int var8 = this.chunk_Z + this.randomGenerator.nextInt(16);
|
||||
par2WorldGenerator.generate(this.currentWorld, this.randomGenerator, var6, var7, var8);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard ore generation helper. Generates Lapis Lazuli.
|
||||
*/
|
||||
protected void genStandardOre2(int par1, WorldGenerator par2WorldGenerator, int par3, int par4) {
|
||||
for (int var5 = 0; var5 < par1; ++var5) {
|
||||
int var6 = this.chunk_X + this.randomGenerator.nextInt(16);
|
||||
int var7 = this.randomGenerator.nextInt(par4) + this.randomGenerator.nextInt(par4) + (par3 - par4);
|
||||
int var8 = this.chunk_Z + this.randomGenerator.nextInt(16);
|
||||
par2WorldGenerator.generate(this.currentWorld, this.randomGenerator, var6, var7, var8);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates ores in the current chunk
|
||||
*/
|
||||
protected void generateOres() {
|
||||
this.genStandardOre1(20, this.dirtGen, 0, 128);
|
||||
this.genStandardOre1(10, this.gravelGen, 0, 128);
|
||||
this.genStandardOre1(20, this.coalGen, 0, 128);
|
||||
this.genStandardOre1(20, this.ironGen, 0, 64);
|
||||
this.genStandardOre1(2, this.goldGen, 0, 32);
|
||||
this.genStandardOre1(8, this.redstoneGen, 0, 16);
|
||||
this.genStandardOre1(1, this.diamondGen, 0, 16);
|
||||
this.genStandardOre2(1, this.lapisGen, 16, 16);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
public class BiomeEndDecorator extends BiomeDecorator {
|
||||
protected WorldGenerator spikeGen;
|
||||
|
||||
public BiomeEndDecorator(BiomeGenBase par1BiomeGenBase) {
|
||||
super(par1BiomeGenBase);
|
||||
this.spikeGen = new WorldGenSpikes(Block.whiteStone.blockID);
|
||||
}
|
||||
|
||||
/**
|
||||
* The method that does the work of actually decorating chunks
|
||||
*/
|
||||
protected void decorate() {
|
||||
this.generateOres();
|
||||
|
||||
if (this.randomGenerator.nextInt(5) == 0) {
|
||||
int var1 = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
|
||||
int var2 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
|
||||
int var3 = this.currentWorld.getTopSolidOrLiquidBlock(var1, var2);
|
||||
|
||||
if (var3 > 0) {
|
||||
;
|
||||
}
|
||||
|
||||
this.spikeGen.generate(this.currentWorld, this.randomGenerator, var1, var3, var2);
|
||||
}
|
||||
|
||||
if (this.chunk_X == 0 && this.chunk_Z == 0) {
|
||||
EntityDragon var4 = new EntityDragon(this.currentWorld);
|
||||
var4.setLocationAndAngles(0.0D, 128.0D, 0.0D, this.randomGenerator.nextFloat() * 360.0F, 0.0F);
|
||||
this.currentWorld.spawnEntityInWorld(var4);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user